带功能的'React Hook useEffect has a missing dependency'警告



所以我有一个React组件,它使用useEffect()钩子:

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忽略评论外,还有什么更实用的方法吗?我发现这些东西使得使用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,据我所知,您希望在某个状态更新时调用某个函数。为此,我建议您编写一个自定义函数,该函数将在更新的地方被调用(例如Input)。

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

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

小示例代码:

const [stateItem, setStateItem] = useState(0);
const myFunction = () => {
// do something
};
const myOtherFunc = (value) => {
setStateItem(value);
if (condition) {
myFunction();
}
};

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

TLDR:将myFunction添加到依赖数组中,如下

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

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

const [stateItem, setStateItem] = useState(0);
useEffect(() => {
if (condition) {
myFunction();
}
}, [stateItem, myFunction]);
const myFunction = () => {
return 'hello';
}

相关内容

  • 没有找到相关文章

最新更新