由于闭包问题,开发者在某些作用域中得到了过时的state。
创造stale closure:
import react, { useState, useRef, useEffect } from "react"; export default function StaleClosure() { let [count, setCount] = useState(null) const countRef = useRef(null) console.log(`re-render?`) useEffect(() => { const intervalId = setInterval(() => { // console.log(`countRef.current`, countRef.current) setCount(count + 1) // setCount(count++) // setCount(state => state + 1) // countRef.current = countRef.current + 1 // setCount(countRef.current) }, 500) return () => clearInterval(intervalId) }, []) return <span style={{ fontSize: 50 }}>{count}</span> }复制成功
StaleClosure函数作用域的count变量,形成闭包,而且是 stale closure。 StaleClosure不会re-render。stale closure的存在,想要在setInterval的传参函数加入拦截的时候,访问count变量不是一个好操作。useEffect(() => { const intervalId = setInterval(() => { // if (count >= 10) return //无法拦截,count永远是初始值 if (countRef.current >= 10) return //可以拦截 console.log(`comparison`, count, countRef.current) // setCount(count + 1) // setCount(count++) setCount(state => state + 1) countRef.current = countRef.current + 1 // setCount(countRef.current) }, 500) return () => clearInterval(intervalId) }, [])复制成功