函数

时间:2019-11-29 10:29:26

标签: javascript reactjs react-hooks

所以我有这个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钩子使这些事情变得不切实际。

4 个答案:

答案 0 :(得分:1)

因此,看来您的目标是将功能保留在组件内部

  1. 您不想将其移动到public class LOC { private int idLoc; private int idProd; private float PrixJour; private int MaxJour; private int idClient; public LOC(int idLoc, int idProd, float PrixJour, int MaxJour, int idClient) { this.idLoc = idLoc; this.idProd = idProd; this.PrixJour = PrixJour; this.MaxJour = MaxJour; this.idClient=idClient; } public LOC( int idProd, float PrixJour, int MaxJour, int idClient) { this.idProd = idProd; this.PrixJour = PrixJour; this.MaxJour = MaxJour; this.idClient=idClient; 内,因为您想在其他地方使用它
  2. 您不想将其移出函数,因为您要避免从组件传递参数

在这种情况下,我认为最好的解决方案是使用如下所示的useEffect钩子

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()} /> ); } 钩子将确保您的函数在每次重新渲染时始终保持不变,因此将其放入deps数组中不会有任何问题。仅当useCallback挂钩的依赖项更改时,该函数才会更改。通过这样做,我们保持了钩子的黄金法则,即从不说谎关于您的依赖。希望能有所帮助。您可能需要阅读此Blog Post By Dan Abramov

答案 1 :(得分:0)

TLDR :将myFunction添加到如下所示的依赖项数组中

React useEffect具有一个称为依赖项数组的东西,这基本上可以帮助您并作出反应以知道何时重新运行该效果。基本上,您应该将所有定义在效果之外的东西放进去。

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

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

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

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

答案 2 :(得分:0)

我对此有疑问。

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

答案 3 :(得分:0)

据我所知,我建议您完全不要使用useEffect,只要您要更新某个状态就想调用某个函数。为此,我建议您编写一个自定义函数,该函数将在将要更新的地方被调用(例如Input)。

现在,您可以调用此函数并更新状态,因为您知道仅在将要更新此特定状态时才调用此函数,然后可以再调用其他函数。

如果您有一个诸如changeHandler之类的东西,您也可以在其中进行,但我建议写一个自定义函数。

小示例代码:

#0  0x00007ffff78455d0 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#1  0x00007ffff7845cd3 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#2  0x00007ffff75a8f21 in __GI___dl_iterate_phdr (callback=0x7ffff7845890, data=0x7fffff7ff170) at dl-iteratephdr.c:75
#3  0x00007ffff7846b31 in _Unwind_Find_FDE () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#4  0x00007ffff7843223 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#5  0x00007ffff7844400 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#6  0x00007ffff78448fe in _Unwind_RaiseException () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#7  0x00007ffff7aded17 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x0000555555554c10 in main ()

希望我能正确理解您的问题,这对您有所帮助。