React 警告:渲染其他组件时无法更新组件?
报错信息:
代码:
function Answer (props) {
const [countDown, setCountDown] = useState(3)
if (countDown > 0) {
setTimeout(() => {
setCountDown(countDown - 1)
}, 1000);
} else {
props.setStatus('guessing')
}
return (
<Fragment>
<div className="box" style={props.style}></div>
<span className="num">{countDown}</span>
</Fragment>
)
}
问题描述:子组件是一个倒计时组件,当倒计时结束时,修改父组件的状态去渲染其他组件。请问要如何处理?
回复
1个回答

test
2024-07-16
这种写法在 React 中是不正确的,每次更新 state 时,函数组件都会重新执行一遍,父组件的状态更新也会导致 该组件 重新执行,所以你的实现有如下问题
- 如果不是 countDown 引起的更新,不应该创建定时器
- 如果在倒计时未完成的情况下,组件就被卸载了,但定时器并没有被清除,计时完成后任然会调用 setCountDown,导致 React 报异常
正确的实现需要用到 useEffect 来处理副作用 和 清除依赖,如下
function Answer (props) {
const [countDown, setCountDown] = useState(3)
useEffect(() => {
let timer;
if (countDown > 0) {
timer = setTimeout(() => {
setCountDown(countDown - 1)
}, 1000);
} else {
props.setStatus('guessing')
}
return () => {
// 组件卸载时,清除定时器
if (timer) {
clearTimeout(timer)
}
}
}, [countDown])
return (
<Fragment>
<div className="box" style={props.style}></div>
<span className="num">{countDown}</span>
</Fragment>
)
}
回复

适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容