【发布时间】:2021-09-05 20:14:01
【问题描述】:
我知道这似乎是一个不寻常的例子,但我似乎仍然无法准确解释为什么我在单击div 后从未在控制台上看到valueB 打印?
请注意,由于我在 setTimeout 中调用了两个设置状态调用,它们不是批处理的。
function App() {
let [a, setA] = React.useState();
let [b, setB] = React.useState();
React.useEffect(() => {
console.log('Entering useEffect', a, b);
return () => {
console.log('Entering cleanup', a, b);
setA(null);
setB(null);
};
}, [a, b]);
console.log('Render', a, b);
return (
<div
onClick={() => {
setTimeout(() => {
setA('valueA');
setB('valueB');
}, 100);
}}
>
<h1>Test App</h1>
</div>
);
}
ReactDOM.render(
<App/>,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
【问题讨论】:
-
在效果清理中调用状态 updaters 对我来说似乎是错误的。这仅用于测试目的吗?如果您删除这些,您将逐渐获得充满值的
a和b。因此,这很可能是 问题 的原因,那么问题是从清理函数更新状态是否可接受?我找不到任何支持或反对它的建议,是吗? -
@Yoshi 是的,正如我提到的,我也知道这是因为
setB(null)而发生的,但我对更确切的步骤感兴趣,了解发生了什么以及为什么valueB从未出现在控制台日志中。 PS 不,我没有看到建议不要在清理功能中使用设置状态。 -
不寻常的例子,但似乎因为
a的值首先发生变化,所以它会在@987654333 的值之前触发useEffect两次(一次通过单击,再次通过useEffect 清理) @ 变化。到它在超时调用setB时,它已经被更新的更新覆盖了两次。这个example 表明React 正在排队状态更新,以防止b的值在使用超时 时过时(“hello”)。 -
@PeterB 官方文档有说吗?有链接吗?
-
@PeterB 那不一样,它并没有说不要在清理函数中调用 setState 。在未安装的组件中调用状态更新程序是另一回事。
标签: javascript reactjs react-hooks