繁体   English   中英

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

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

所以我有这个使用 useEffect() 钩子的 React 组件:

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

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

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

React 警告我“myFunction”是一个缺失的依赖项。 我(认为我)理解为什么并且我已经阅读了许多要求或多或少相同的问题的类似问题,但答案始终是“将您的函数移动到 useEffect 钩子中”。 如果不是从不同的地方调用 myFunction,这会很好,例如:

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

因此我不能将我的函数放在 useEffect 钩子中。

类似问题的一个答案是将函数放在组件之外,但这需要我将大量数据传递给我的函数,例如const myFunction(stateItem, setStateItem, someProp) => { stuff };

当有几个函数有很多道具、状态钩子等要传递时,这会变得非常乏味。

除了在 useEffect 钩子上方放置一个 linter ignore 注释之外,还有什么更实用的方法可以解决这个问题吗? 我发现这些东西使使用 React 钩子非常不切实际。

我遇到了这个问题。

React 总是试图让你的效果保持最新。 如果您不传递依赖项数组,React 将在每次渲染后运行该效果,以防万一。

这将在每个渲染上运行

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

如果你传递一个空数组,你基本上是在告诉你你的效果不依赖于任何东西,并且只运行一次是安全的。

这只会运行一次

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

如果您填充依赖项数组,则表示您的效果取决于那些特定的事物,如果其中任何一个发生变化,则效果需要再次运行,否则就不必了。

这只会在somePropsomeFunction更改时运行。

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

注意:记住函数、对象和数组是通过引用比较的

所以,基本上你的选择是:

  • 将函数移动到效果的主体。
  • 添加它做依赖数组

如果选择将其添加到数组中,则需要决定以下事项:

如果该功能被修改,您是否需要再次运行效果?

如果这是真的,只需将它添加到依赖项数组,React 将负责在每次函数更改时重新运行您的效果。

如果这不是真的,请将您的函数包装到useCallback以便您可以在渲染中保持其引用相同。 您还可以向useCallback添加依赖项数组以控制何时需要重新创建函数。

EXTRA函数需要重新创建,但您不想重新运行。

  • 使用useRef()添加一些变量以跟踪效果是否运行过一次,并在您的效果中写入检查以停止效果,如果它之前运行过。 喜欢:
const effectHasRun_ref = useRef(false);
useEffect(()=>{
  if (effectHasRun_ref.current === true) {
    return;
  }
  else {
    // RUN YOUR EFFECT
    effectHasRun_ref.current = true;
  }
},[yourFunction]);

因此,您的目标似乎是将您的功能保留在您的组件中,并且

  1. 您不想将它移动到useEffect因为您想在其他地方使用它
  2. 你不想把它移到你的函数之外,因为你想避免从组件传递参数

在这种情况下,我认为最好的解决方案是使用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()} />
   );
}


useCallback钩子将确保您的函数在每次重新渲染时始终保持不变,因此将它放在 deps 数组中不会有任何问题。 该函数仅在 useCallback 钩子的依赖项更改时才会更改。 通过这样做,我们保持了钩子的黄金法则,永远不要对你的依赖撒谎 希望有帮助。 您可能想阅读Dan Abramov 撰写的这篇博客文章

我建议你根本不要使用 useEffect ,据我所知,你想在更新某个状态时调用某个函数。 为此,我建议您宁愿编写一个自定义函数,该函数将在更新时调用(例如输入)。

现在你可以调用这个函数并更新你的状态,因为你知道这个函数只会在只有这个特定状态即将更新时才会被调用,然后你可以调用你的另一个函数。

如果你有类似 changeHandler 的东西,你也可以在那里做,但我宁愿建议写一个自定义函数。

小示例代码:

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

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

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

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

我希望我正确理解了您的问题,这很有帮助。

您可以使用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 :将 myFunction 添加到依赖项数组,如下所示

React useEffect 有一个叫做依赖数组的东西,它的作用基本上可以帮助你并知道何时重新运行效果。 基本上你应该把所有定义的东西都放在效果之外。

在此效果中,您将 stateItem 作为此效果的依赖项,这意味着每次更改时,react 都会重新运行此效果。 现在,您可能已经猜到您正在使用myFunction ,它在效果之外也有很好的定义,这意味着 react 应该知道它何时更新,以便它知道。 要修复此警告,只需像这样将函数在依赖项数组中包含一个项即可。

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