简体   繁体   English

'React Hook useEffect has an missing dependency' 警告功能

[英]'React Hook useEffect has a missing dependency' warning with function

So I have this React component which uses the useEffect() hook:所以我有这个使用 useEffect() 钩子的 React 组件:

const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem]);

const myFunction = () => {
  return 'hello';
}

React gives me a warning about 'myFunction' being a missing dependency. React 警告我“myFunction”是一个缺失的依赖项。 I (think I) understand why and I've read through many similar questions asking for more or less the same thing, but the answer is always 'move your function into the useEffect hook'.我(认为我)理解为什么并且我已经阅读了许多要求或多或少相同的问题的类似问题,但答案始终是“将您的函数移动到 useEffect 钩子中”。 This would be fine if not for myFunction being called from different places, eg:如果不是从不同的地方调用 myFunction,这会很好,例如:

...
return (
  <Button onClick={() => myFunction()} />
);

therefore I cannot put my function inside the useEffect hook.因此我不能将我的函数放在 useEffect 钩子中。

One answer to a similar question was to put the function outside the component, but that would require me to pass a lot of data to my functions, eg const myFunction(stateItem, setStateItem, someProp) => { stuff };类似问题的一个答案是将函数放在组件之外,但这需要我将大量数据传递给我的函数,例如const myFunction(stateItem, setStateItem, someProp) => { stuff };

which gets extremely tedious when there are several functions with many props, state hooks etc. to pass.当有几个函数有很多道具、状态钩子等要传递时,这会变得非常乏味。

Aside from putting a linter ignore comment above the useEffect hook, is there anything more practical to do about this?除了在 useEffect 钩子上方放置一个 linter ignore 注释之外,还有什么更实用的方法可以解决这个问题吗? I'm finding these things to make using react hooks very impractical.我发现这些东西使使用 React 钩子非常不切实际。

I've had issues with this.我遇到了这个问题。

React is always trying to keep your effects up-to-date. React 总是试图让你的效果保持最新。 If you don't pass a dependency array, React will run that effect after every render, just in case.如果您不传递依赖项数组,React 将在每次渲染后运行该效果,以防万一。

This will run on every render这将在每个渲染上运行

useEffect(()=> {
  // DO SOMETHING
});

If you pass an empty array, you're basically telling that your effect does not depend on anything, and it's safe to run it only once.如果你传递一个空数组,你基本上是在告诉你你的效果不依赖于任何东西,并且只运行一次是安全的。

This will only run once这只会运行一次

useEffect(()=> {
  // DO SOMETHING
},[]);

If you populate the dependency array, you're telling the your effect depend on those specific things, and if any of them changes, the effect needs to be run again, otherwise, it doesn't have to.如果您填充依赖项数组,则表示您的效果取决于那些特定的事物,如果其中任何一个发生变化,则效果需要再次运行,否则就不必了。

This will only run if someProp or someFunction changes.这只会在somePropsomeFunction更改时运行。

useEffect(()=> {
  // DO SOMETHING
},[someProp,someFuction]);

NOTE: Remember functions, objects and arrays are compared by reference注意:记住函数、对象和数组是通过引用比较的

So, basically your options are:所以,基本上你的选择是:

  • Move the function to the effect's body.将函数移动到效果的主体。
  • Add it do the dependency array添加它做依赖数组

If you choose to add it to the array, you need to decide the following:如果选择将其添加到数组中,则需要决定以下事项:

If that function gets modified, do you need your effect to run again?如果该功能被修改,您是否需要再次运行效果?

If this is true, simply add it to the dependency array and React will take care of re-running your effect every time that function changes.如果这是真的,只需将它添加到依赖项数组,React 将负责在每次函数更改时重新运行您的效果。

If this is not true, wrap your function into a useCallback so you can keep its reference the same across renders.如果这不是真的,请将您的函数包装到useCallback以便您可以在渲染中保持其引用相同。 You can also add a dependency array to the useCallback to control when the function needs to be recreated, or not.您还可以向useCallback添加依赖项数组以控制何时需要重新创建函数。

EXTRA The function needs to be recreated, but you don't want to re-run. EXTRA函数需要重新创建,但您不想重新运行。

  • Add some variable using useRef() to keep track of whether the effect has run once, and write a check into your effect to stop the effect if it's has run before.使用useRef()添加一些变量以跟踪效果是否运行过一次,并在您的效果中写入检查以停止效果,如果它之前运行过。 Like:喜欢:
const effectHasRun_ref = useRef(false);
useEffect(()=>{
  if (effectHasRun_ref.current === true) {
    return;
  }
  else {
    // RUN YOUR EFFECT
    effectHasRun_ref.current = true;
  }
},[yourFunction]);

So it seems like your aim is to keep your function inside your component and因此,您的目标似乎是将您的功能保留在您的组件中,并且

  1. You don't want to move it inside useEffect since you want to use it elsewhere您不想将它移动到useEffect因为您想在其他地方使用它
  2. You don't want to move it outside your function since you want to avoid passing parameters from the component你不想把它移到你的函数之外,因为你想避免从组件传递参数

In that case you i think the best solution is to use the useCallback hook as shown below在这种情况下,我认为最好的解决方案是使用useCallback钩子,如下所示


function YourComponent(props){

  const [stateItem, setStateItem] = useState(0);

  //wrap your logic in useCallback hook
  const myFunction = React.useCallback(
    () => {

      //if you use any dependencies in this function add them to the deps array of useCallback
      //so if any of the dependencies change thats only when the function changes

      return 'hello'
    }, [deps])

    useEffect(() => { 
       if(condition) {
          myFunction();
       }

    //add your function to the dependency array as well
    //the useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array, besides the #1 rule is NEVER LIE ABOUT YOUR DEPENDENCIES
    //the function only changes if the dependencies to useCallback hook change!!
    }, [stateItem, myFunction ])

   return (
     <Button onClick={() => myFunction()} />
   );
}


The useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array. useCallback钩子将确保您的函数在每次重新渲染时始终保持不变,因此将它放在 deps 数组中不会有任何问题。 the function only changes if the dependencies to useCallback hook change.该函数仅在 useCallback 钩子的依赖项更改时才会更改。 By doing this we keep the golden rule of hooks which is NEVER LIE ABOUT YOUR DEPENDENCIES .通过这样做,我们保持了钩子的黄金法则,永远不要对你的依赖撒谎 Hope that helps.希望有帮助。 You might want to read this Blog Post By Dan Abramov您可能想阅读Dan Abramov 撰写的这篇博客文章

I would suggest you not to use the useEffect at all, as far as I understood, you want to call a certain function whenever a certain state was updated.我建议你根本不要使用 useEffect ,据我所知,你想在更新某个状态时调用某个函数。 For this, I would suggest you rather to write a custom function which will be called on the spot where it would be updated (for example an Input).为此,我建议您宁愿编写一个自定义函数,该函数将在更新时调用(例如输入)。

Now you could just call this function and update your state, since you know this function will only be called when only this particular state is about to be updated and then you can call your other function afterwards.现在你可以调用这个函数并更新你的状态,因为你知道这个函数只会在只有这个特定状态即将更新时才会被调用,然后你可以调用你的另一个函数。

If you have something like a changeHandler you could also do it in there but I would rather suggest to write a custom function.如果你有类似 changeHandler 的东西,你也可以在那里做,但我宁愿建议写一个自定义函数。

Small example code:小示例代码:

const [stateItem, setStateItem] = useState(0);

const myFunction = () => {
   // do something
};

const myOtherFunc = (value) => {
   setStateItem(value);

   if (condition) {
      myFunction();
   }
};

I hope I understood your problem correctly and this was helpful.我希望我正确理解了您的问题,这很有帮助。

You can use useRef() instead of onClick to call that function, though this is primarily use to access the DOM but it works. 您可以使用useRef()代替onClick来调用该函数,尽管该函数主要用于访问DOM,但它可以工作。

const [stateItem, setStateItem] = useState(0);

const onClickRef = React.useRef();

useEffect(() => {

  const myFunction = () => {
    return 'hello';
  }

  if (condition) {
   onClickRef.current.addEventListener('click', myFunction);
  }

}, [stateItem]);

return (
  <Button ref={onClickRef} />
);

TLDR : Add myFunction to dependency array like below TLDR :将 myFunction 添加到依赖项数组,如下所示

React useEffect has thing called dependency array what this does basically helps you and react to know when to re run the effect. React useEffect 有一个叫做依赖数组的东西,它的作用基本上可以帮助你并知道何时重新运行效果。 Basically you should put everything that is defined outside the effect.基本上你应该把所有定义的东西都放在效果之外。

In this effect you are putting stateItem as a dependency of this effect this means that every time it changes react will re run this effect.在此效果中,您将 stateItem 作为此效果的依赖项,这意味着每次更改时,react 都会重新运行此效果。 Now as you might have guess you are using myFunction which is as well defined outside the effect, which means that react should know when that updates so it is aware.现在,您可能已经猜到您正在使用myFunction ,它在效果之外也有很好的定义,这意味着 react 应该知道它何时更新,以便它知道。 To fix this warning just put the function has a item in the the dependency array like this.要修复此警告,只需像这样将函数在依赖项数组中包含一个项即可。

const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem, myFunction]);

const myFunction = () => {
  return 'hello';
}

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

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