我有一个关于以下(非常奇怪的)问题的问题。
我有一个这样的父组件:
function ParentComponent() {
const [myParam, setMyParam] = React.useState(1);
useEffect(() => {
setTimeout(() => {
console.log('Setting myParam to 0...');
setMyParam(0);
}, 3000);
}, []);
return (
<div>
<ChildComponent myparam={myParam}></ChildComponent>
</div>
)
}从这个父组件中,我将参数myParam (默认值为1)作为一个属性传递给子组件。
子组件如下所示:
function ChildComponent(props) {
const loop = () => {
if(props.myparam) { // DOES NOT DETECT PROP CHANGE PROPERLY!!!
setTimeout(() => loop(), 1000)
}
}
React.useEffect(() => {
if(props.myparam) {
loop();
}
}, [props.myparam])
return (
<div>
Loop demo
</div>
)
}myparam的初始值是1,因此loop函数开始递归。
然后,父组件在3秒后更新属性,并且它在子组件的useEffect()钩子中被正确检测到,但循环函数没有检测到属性更改,并继续递归运行。
在我看来,预期的行为是递归函数(loop())应该在属性myparam获得值0(从父组件更改)之后停止执行,因为在loop()函数中,我有这样的IF语句:
if(props.myparam) { // DOES NOT DETECT PROP CHANGE PROPERLY!!!
setTimeout(() => loop(), 1000)
}对这种奇怪的行为有什么解释吗?
提前感谢!
发布于 2020-11-23 19:25:16
我对自己负责,因为我相信我找到了答案。
在loop()函数中不使用props.myparam作为条件:
if(props.myparam) { // DOES NOT DETECT PROP CHANGE PROPERLY!!!
setTimeout(() => loop(), 1000)
}我使用局部变量作为标志:
if(runLoop) {
setTimeout(() => loop(), 1000)
}在ChildComponent的useEffect()中,我有这样的代码:
React.useEffect(() => {
if(props.myparam) {
runLoop = 1;
loop();
} else {
runLoop = 0;
}
return () => {
runLoop = 0; // this solves the issue
}
}, [props.myparam])然后,在ChildComponent的useEffect()中,我添加了一个清理函数,将runLoop设置为false -脚本按预期工作。
所以我的结论是,React基本上在每次渲染时实例化组件,以前渲染的变量不会更新(除非它们在清理时显式更新)。
https://stackoverflow.com/questions/64943742
复制相似问题