在我的 React 应用程序中,我有一个 redux 存储,其中包含具有以下模型的用户:
{
id: "",
name: "",
email: "",
isAdmin: false,
client: { id: undefined },
token: "",
tokenExpiry: null
};
在一个简单的页面上,我正在查询数据库中与该用户关联的其他数据。为此,我正在利用useEffect
钩子:
useEffect(() => {
// Check JWT auth token and refresh if near expiry
auth.refresh(
{ token: user.token, tokenExpiry: user.tokenExpiry },
// Request user "field" data
loadFields(user.client.id, user.token)
);
}, [user.client.id, user.token]);
在构建时,React 会发出React Hook useEffect has missing dependencies: 'loadFields' and 'user.tokenExpiry'. Either include them or remove the dependency array
警告。
如果我理解正确useEffect
,第二个参数是 Reach 将"监视"的值,在任何更改时,组件将被重新渲染(类似于componentDidUpdate
的工作方式(......
虽然我的useEffect
调用中使用了其他值,但我只想在更改user.client.id
或user.token
时重新处理此函数。这是为了避免在更改用户模型的其他部分时进行不必要的重新渲染,因此我不想添加user.tokenExpiry
作为依赖项。
由于loadFields
函数也是在useEffect
逻辑之外使用的函数,因此我无法将其放置在useEffect
中,因此我尝试将其添加为依赖项,但这会导致重新渲染循环,因为它在其中具有dispatch
调用:
const loadFields = async (clientId, token) => {
setIsLoading(true);
try {
await dispatch(fetchFields(clientId, token));
setIsLoading(false);
} catch (error) {
setIsLoading(false);
dispatch(resetFields());
}
};
那么在这种情况下,useEffect
的正确方法是什么?
要在依赖项列表中包含loadFileds
函数,请尝试像这样用React.useCallback
钩子包装它
React.useCallback(async (clientId, token) => { ... }, []);
并将其添加到依赖项列表中。useCallback
"记住"函数并且不会在每次渲染时创建它,因此loadFields
渲染之间保持不变,并且不会触发effect
,请参阅文档。
tokenExpiry
呢 - 好吧,有时会发生这种情况,我通常会发表评论,描述为什么某些变量不在依赖项列表中。
将所有依赖项添加到数组中
useEffect(() => {
// Check JWT auth token and refresh if near expiry
auth.refresh(
{ token: user.token, tokenExpiry: user.tokenExpiry },
// Request user "field" data
loadFields(user.client.id, user.token)
);
}, [user.client.id, user.token, user.tokenExpiry]);
或者它可能只是被你的反应钩子标记,你可以为那一行禁用它。
useEffect(() => {
// Check JWT auth token and refresh if near expiry
auth.refresh(
{ token: user.token, tokenExpiry: user.tokenExpiry },
// Request user "field" data
loadFields(user.client.id, user.token)
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user.client.id, user.token]);
我通常也会在覆盖上方留下评论,以了解其原因。请谨慎使用,因为当您对效果钩子进行任何更改时,它可能会更改您希望钩子"监视"更改的内容。
建议:将tokenExpry
添加到数组,如果可以判断出终结点接近需要刷新,则有条件地调用终结点。
useEffect(() => {
// Check JWT auth token and refresh if near expire
if ( /* tokenExpiry almost expired */ ) {
auth.refresh(
{ token: user.token, tokenExpiry: user.tokenExpiry },
// Request user "field" data
loadFields(user.client.id, user.token)
);
}
}, [user.client.id, user.token, user.tokenExpiry]);