useEffectEvent (React19.2)
useEffectEvent 允许创建一个函数,这个函数专门用于在effect中调用,函数中引用的props/state不受effect回调函数闭包影响,永远能拿到最新的props/state值。在某些情况下,你可能只想在 Effect 中读取最新的 props 或 state,而不希望当这些值改变时让 Effect 重新运行。要在 Effect 中读取最新的 props 或 state,而不让这些值成为响应式依赖,请把它们放进一个 Effect Event 中。
解决闭包陷阱
闭包陷阱代码
export default function CloserBug() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
console.log(count);
}, 1000);
return () => clearInterval(timer);
}, []);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}传统解决方案1
export default function CloserBug() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
console.log(count);
}, 1000);
return () => clearInterval(timer);
}, [count]);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}传统解决方案2
export default function CloserBug() {
const [count, setCount] = useState(0);
const countRef = useRef(count);
useEffect(() => {
const timer = setInterval(() => {
console.log(count);
}, 1000);
return () => clearInterval(timer);
}, [count]);
const handleClick = () => {
setCount(count + 1);
countRef.current = count;
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}使用useEventEffect
export default function CloserBug() {
const [count, setCount] = useState(0);
const onCount = useEffectEvent(() => {
console.log(count);
})
useEffect(() => {
const timer = setInterval(() => {
onCount()
}, 1000);
return () => clearInterval(timer);
}, []);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}