避免 JSX 回调中的闭包陷阱
在 React 中,闭包陷阱是常见的问题,特别是在事件处理函数、定时器和副作用中。以下是一些有效的避免方法:
1. 使用函数式更新
错误代码:
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
// 闭包陷阱:count 是创建时的值
setCount(count + 1);
};
return <button onClick={handleClick}>Count: {count}</button>;
}
解决方案:
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
// 使用函数式更新,获取最新状态
setCount(prevCount => prevCount + 1);
};
return <button onClick={handleClick}>Count: {count}</button>;
}
2. 使用 useRef 保存可变值
问题代码:
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
// 闭包陷阱:time 始终是初始值 0
setTime(time + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>Time: {time}</div>;
}
解决方案:
function Timer() {
const [time, setTime] = useState(0);
const timeRef = useRef(time);
// 同步 ref 与 state
useEffect(() => {
timeRef.current = time;
}, [time]);
useEffect(() => {
const interval = setInterval(() => {
// 使用 ref 获取最新值
setTime(timeRef.current + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>Time: {time}</div>;
}