复用 hook 是通过传递 state 变量:
import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}重点在于:
- 即使
isOnline是在useFriendStatus中被调用的,它实际上是存储在FriendStatus函数的实例中的。这意味着它在FriendStatus的实例中的值,跟另外一个使用useFriendStatus的函数式组件(如FriendListItem)之间是不共享 - 本质上,
FriendStatus调用useFriendStatus的过程,可以当作把后者的实现拷贝过来 useFriendStatus的参数可以任意定,它需要什么就传什么;对于返回值,如果返回的内容有多个,可以用 object 包裹一下
同时,一个 hook 它的参数可以是另外一个 hook 的返回值,比如下面 useFriendStatus 使用的是 useState 的返回值。这意味着你可以把 state 中的变量作为参数传给 hook:
function ChatRecipientPicker() {
const [recipientID, setRecipientID] = useState(1);
const isRecipientOnline = useFriendStatus(recipientID);
return (
<>
<Circle color={isRecipientOnline ? 'green' : 'red'} />
<select
value={recipientID}
onChange={e => setRecipientID(Number(e.target.value))}
>
{friendList.map(friend => (
<option key={friend.id} value={friend.id}>
{friend.name}
</option>
))}
</select>
</>
);
}我做了个视频讲解: