在 official docs of Custom React Hooks 中,使用自定义钩子的一个示例是:
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
但是,第一次设置isOnline
时,值应该是null
,因为自定义钩子的初始状态是null
,所以我认为它只是返回{{1 }}:
null
由于 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;
}
是一个 AJAX 调用,所以当代码最终执行 ChatAPI.subscribeToFriendStatus()
时,比如说,0.7 秒后,这实际上如何触发 setIsOnline(true)
重新呈现?
状态在组件内部是有意义的,所以我们可以FriendListItem()
并导致组件重新渲染。但是一个函数如何导致另一个函数(组件)被重新渲染?
换句话说,函数 A 如何从函数 B 取回 setData()
,而函数 B 中设置的某些东西可以神奇地触发函数 A 运行?
答案 0 :(得分:2)
React 提供了一些“原生”钩子(例如 useState
、useEffect
等)。所有自定义钩子都只是在某些时候调用原生钩子(或另一个遵守此规则的自定义钩子)的函数。
考虑这两种情况:
const A = () => {
const [s1, setS1] = useState()
const [s2, setS2] = useState()
...
}
和
const useMyHook = () => {
const [s2, setS2] = useState()
// ..maybe do something here
return [s2, setS2]
}
const B = () => {
const [s1, setS1] = useState()
const [s2, setS2] = useMyHook()
...
}
如果您按照调用顺序进行操作,您会发现在这两种情况下,我们只有两个 useState
调用。
本质上,自定义钩子在 React 眼中是“扁平化的”,它只关心正在渲染的组件和原生钩子的执行顺序。
答案 1 :(得分:1)
简而言之,自定义钩子没有做任何特别的事情,它只是一个函数。之所以这样称呼它们,是因为它们使用“原始”钩子,因此必须按照钩子规则使用。
当 React 执行一个组件时,它会跟踪它引用的是哪个实例,并且所有钩子都附加到该组件上。
这意味着实际上,useState
是在调用 useFriendStatus
的组件范围内执行的,因此 React 知道当状态被 {{1 }}。