闭包问题的本质是异步操作和事件处理函数,总是会捕获到定义的值,而不是最新的值。
通过useRef创建一个持久引用,使得他总是获取到最新的值。
ts
/** 用于解决useState的闭包问题 */
export function useLatest<T>(props: T) {
const current = useRef<T>(props);
current.current = props;
return current;
}
tsx
// 闭包问题示例
function Counter() {
const [count, setCount] = useState(0);
// 有闭包问题的写法
useEffect(() => {
const timer = setTimeout(() => {
console.log(count); // 永远是0,因为捕获了初始渲染时的count值
}, 2000);
return () => clearTimeout(timer);
}, []); // 依赖数组为空
// 使用useLatest解决闭包问题
const latestCount = useLatest(count);
useEffect(() => {
const timer = setTimeout(() => {
console.log(latestCount.current); // 正确获取最新count值
}, 2000);
return () => clearTimeout(timer);
}, []); // 依赖数组仍为空
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}