Reactjs useEffect依赖项列表及其包含所有使用变量的最佳实践

Reactjs useEffect依赖项列表及其包含所有使用变量的最佳实践,reactjs,react-hooks,use-effect,Reactjs,React Hooks,Use Effect,根据使用useEffect依赖项数组时的react文档,您应该传入效果中使用的所有值 如果使用此优化,请确保数组包含组件范围中随时间变化且效果使用的所有值(如道具和状态)。否则,代码将引用以前渲染中的过时值。了解有关如何处理函数的更多信息,以及当数组值更改太频繁时如何执行 我不知道钩子在幕后是如何工作的,所以我在这里猜。 由于闭包中的变量可能会过时,这意味着函数被缓存在某个地方。但是为什么要缓存函数,因为它没有被调用,除非依赖项发生了变化,并且无论如何都需要重新创建函数 我做了一个小的测试组件

根据使用useEffect依赖项数组时的react文档,您应该传入效果中使用的所有值

如果使用此优化,请确保数组包含组件范围中随时间变化且效果使用的所有值(如道具和状态)。否则,代码将引用以前渲染中的过时值。了解有关如何处理函数的更多信息,以及当数组值更改太频繁时如何执行

我不知道钩子在幕后是如何工作的,所以我在这里猜。 由于闭包中的变量可能会过时,这意味着函数被缓存在某个地方。但是为什么要缓存函数,因为它没有被调用,除非依赖项发生了变化,并且无论如何都需要重新创建函数

我做了一个小的测试组件

function App() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);

  useEffect(() => {
    console.log("b", b);
  }, [a]);

  return (
    <div>
      <div>App {a}</div>
      <button
        onClick={() => {
          setA(a + 1);
        }}
      >
        AddA
      </button>
      <button
        onClick={() => {
          setB(b + 1);
        }}
      >
        AddB
      </button>
    </div>
  );
}
函数应用程序(){
常数[a,setA]=useState(0);
const[b,setB]=useState(0);
useffect(()=>{
控制台日志(“b”,b);
},[a]);
返回(
App{a}
{
刚毛(a+1);
}}
>
阿达
{
挫折(b+1);
}}
>
AddB
);
}
您可以在这里尝试:它工作得很好,没有过时的值。有人能解释一下我遗漏了什么吗

编辑: 在反馈我的问题不完全清楚后,添加一个更具体的问题:


加载页面后,我单击AddB按钮,然后单击AddA按钮,控制台中显示的值为1。根据文档,我应该得到一个过时的值(0)。为什么不是这样


加载页面后,我单击AddB按钮,然后单击AddA 按钮,控制台中显示的值为1。根据文件,我 应获取一个过时的值(0)。为什么不是这样

在这种情况下,您没有看到过时值的原因是,当您单击
AddA
时,会发生重新渲染。在新渲染中,由于
a
的值不同于以前的渲染,因此
useffect
将计划在用户界面更新后运行(但是,它将引用的值将来自当前渲染-因为传递给
useffect
的函数在其依赖项每次更改时都会重新创建,因此它会从该渲染中捕获值)

由于以上原因,这就是为什么您会看到
b
的新值

但是如果你有这样的代码

React.useEffect(() => {
    const timer = window.setInterval(() => {
       setB(b + 1);
    }, 1000);
    return () => {
      window.clearInterval(timer);
    };
  }, []);
b
将是一个过时的闭包。由于
useffect
没有重新运行,
b
始终具有创建它的渲染中的值,这是第一个渲染,上面的代码无法按预期工作,您可以自己检查


我将在上面添加Patrick Roberts的这条评论,因为它很好地解释了react文档在说“否则,您的代码将引用以前呈现的过时值”时的含义:

问题是,您必须在第一个窗口中单击AddA按钮 在单击AddB和AddA之间,效果引用 从一个陈旧的结尾


请在问题本身中包含您的代码文本。这并不是说它是否是最佳实践,而是说如果您不包含代码,您不知道实际发生了什么变化。如果您在此处发布代码,我们可以帮助您确定是否存在您可能没有考虑的极端情况。代码在他有一个沙盒链接,但我也将其粘贴到了问题中。你能更清楚地表述你的问题吗?在页面加载后,我单击AddB按钮,然后单击AddA按钮,控制台中显示的值是1。根据文档,我应该得到一个过时的值(0)。为什么不是这样?@gmoniava change
useffect(()=>{console.log(“b”),b);}[a]);
useffect(()=>{return()=>{console.log(“b”,b);};};}[a]);
。足够好了吗?感谢这个例子,我可以清楚地看到为什么会有问题。所以我可以假设只列出我想“监视”的依赖项吗所以效果会被重新执行,只要我小心它的作用?@Ivan是的,但大多数时候react团队建议列出所有的效果,因为有时候你认为自己很好,不会有过时的结束,但你可能会。