根据 https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect 的 React 文档当使用 useEffect 依赖数组时,您应该传入效果中使用的所有值。
If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array values change too often.
我不知道这个钩子(Hook)在幕后是如何工作的,所以我在这里猜测。 由于闭包内的变量可能会过时,这意味着该函数已缓存在某处。但是为什么要缓存该函数,因为除非依赖项发生更改并且无论如何都需要重新创建该函数,否则该函数不会被调用?
我制作了一个小型测试组件。
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>
);
}
您可以在这里尝试一下:https://codesandbox.io/s/react-hooks-playground-forked-m5se8而且它运行得很好,没有陈旧的值。有人可以解释一下我缺少什么吗?
编辑: 反馈我的问题不完全清楚后,添加一个更具体的问题:
当页面加载后,我单击 AddB 按钮,然后单击 AddA 按钮时,控制台中显示的值为 1。根据文档,我应该得到一个过时的值 (0)。为什么情况并非如此?
最佳答案
When after a page load I click on AddB button and then click on AddA button, value displayed in console is 1. According to the docs, I should get a stale value (0). Why is this not the case?
在这种情况下,您看不到过时值的原因是,当您单击 AddA
时,会发生重新渲染。在新的渲染中,由于 a
的值与之前的渲染不同,因此 useEffect
将计划在 React 更新 UI 后运行(但是它将引用的值将是 < em>来自当前渲染 - 因为传递给 useEffect
的函数每次其依赖项之一发生更改时都会重新创建,因此它会从该渲染中捕获值)。
由于上述原因,这就是为什么您会看到 b
的新值。
但是如果你有这样的代码
React.useEffect(() => {
const timer = window.setInterval(() => {
setB(b + 1);
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);
b
将是一个过时的闭包。由于 useEffect
没有重新运行,b
始终具有创建它的渲染器中的值,即第一个渲染器,上面的代码将无法按预期工作,您可以自己检查。
我将添加上面 Patrick Roberts 的评论,因为它很好地解释了恕我直言,当 React 文档说“否则,您的代码将引用以前渲染中的陈旧值”时可能意味着什么:
the problem is that you had to click on AddA button in the first place. Between the time you click AddB and AddA, the effect references b from a stale closure
关于reactjs - useEffect 依赖项列表及其包含所有使用的变量的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67676829/