useEffect 的相互竞争
在 React 的项目中我们经常会使用 useEffect
这个hook 去处理组件中的 SideEffect,为确保的组件在每次渲染时都得到同样的数据,React 在开发模式下会对每个 useEffect
函数执行2 次。这种情况如果我们没有正确清除 useEffect
带来的 SideEffect 的话就会形成一种相互竞争 或者 Race Condition。比如下面的例子:
const Com = ({timeout, text}) => {
const ref = useRef()
useEffect(() => {
setTimeout(() => {
ref.textContent = text;
}, timeout)
}, [timeout])
return (<div ref={ref}/>)
}
当父级组件传入不同的值 3000, 3000ms 和 2000,2000ms时,组件会先显示 2000ms 然后3000ms而不是我们设想的只显示2000ms。
解决上面问题的方式就是在 useEffect
被清除的时候我们也需要执行相应的函数清除 SideEffect。
const Com = ({timeout, text}) => {
const ref = useRef()
useEffect(() => {
- setTimeout(() => {
+ const id = setTimeout(() => {
ref.textContent = text;
}, timeout)
+ return () => clearTimeout(id)
}, [timeout])
return (<div ref={ref}/>)
}