简体   繁体   English

反应警告 useEffect 缺少依赖项

[英]React warning useEffect missing dependency

In my React application I have a redux store that contains a user with the following model:在我的 React 应用程序中,我有一个 redux 存储,其中包含具有以下模型的用户:

{
  id: "",
  name: "",
  email: "",
  isAdmin: false,
  client: { id: undefined },
  token: "",
  tokenExpiry: null
};

On a simple page, I am querying a database for other data associated to that user.在一个简单的页面上,我正在查询与该用户关联的其他数据的数据库。 To do so I am taking advantage of the useEffect hook:为此,我利用了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]);

Upon building, React presents the React Hook useEffect has missing dependencies: 'loadFields' and 'user.tokenExpiry'. Either include them or remove the dependency array在构建时,React 显示React Hook useEffect has missing dependencies: 'loadFields' and 'user.tokenExpiry'. Either include them or remove the dependency array React Hook useEffect has missing dependencies: 'loadFields' and 'user.tokenExpiry'. Either include them or remove the dependency array warning. React Hook useEffect has missing dependencies: 'loadFields' and 'user.tokenExpiry'. Either include them or remove the dependency array警告。

If I understand useEffect correctly, the second parameter is the values which Reach will "watch", upon any change the component will be re-rendered (similar to how componentDidUpdate works)...如果我正确理解useEffect ,第二个参数是 Reach 将“监视”的值,在任何更改时,组件都将重新呈现(类似于componentDidUpdate工作方式)...

Whilst there are other values used within my useEffect call, I only want to reprocess this function when the user.client.id or user.token is changed.虽然我的useEffect调用中使用了其他值,但我只想在user.client.iduser.token更改时重新处理此函数。 This is to avoid unnecessary re-renders when other parts of the user model is changed, so I don't want to add user.tokenExpiry as a dependency.这是为了避免在用户模型的其他部分发生更改时进行不必要的重新渲染,因此我不想将user.tokenExpiry添加为依赖项。

As the loadFields function is a function also used outside of from the useEffect logic, I cannot place it within useEffect so I've tried adding it as a dependency, but this causes a re-render loop as it has a dispatch call within it:由于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());
  }
};

So what is the correct way to impelment useEffect in this scenario?那么在这种情况下实现useEffect的正确方法是什么?

Either add all the dependencies to the array要么将所有依赖项添加到数组中

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]);

Or it is likely just being flagged by your react-hooks linter, you can disable it for that line.或者它可能只是被您的 react-hooks linter 标记,您可以为该行禁用它。

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]);

I usually also leave a comment above the override as for the reason for it.我通常也会在覆盖上方发表评论,以了解其原因。 Use this with caution as when you make any changes to the effect hook it can change what you want the hook to "watch" changes of.请谨慎使用,因为当您对效果挂钩进行任何更改时,它可能会更改您希望挂钩“监视”更改的内容。

Suggestion: Add tokenExpry to the array and conditionally call your endpoint if you can tell it is close to needing refreshing.建议:将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]);

To include loadFileds function in the dependency list try to wrap it with React.useCallback hook like this要在依赖项列表中包含loadFileds函数,请尝试像这样使用React.useCallback钩子包装它

React.useCallback(async (clientId, token) => { ... }, []);

and add it to dependency list.并将其添加到依赖项列表中。 useCallback "remembers" the function and doesn't create it on every render, thus loadFields stays the same across renders and it doesn't trigger effect , see Documentation . useCallback “记住”该函数并且不会在每次渲染时创建它,因此loadFields在渲染中保持不变并且不会触发effect ,请参阅文档

What about tokenExpiry - well, sometimes such situations happen, I usually leave a comment, that describes why some variable is not in a dependency list. tokenExpiry怎么tokenExpiry - 好吧,有时会发生这种情况,我通常会发表评论,描述为什么某些变量不在依赖项列表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM