function Component(props) {
const [count, setCount] = useState(() => {
return props.initialCount ?? 0 // ❌ 问题1:初始化函数只执行一次,props变了也不会更新
})
useEffect(() => { // ❌ 问题2:没有依赖数组,每次渲染都执行
if (props.shouldAddListener) {
setTimeout(() => {
window.addEventListener('click', () => { // ❌ 问题3:没有 cleanup 清除监听
setCount(count + 1) // ❌ 问题4:闭包陷阱,count 永远是旧值
})
}, 0)
}
});
const clickFun = () => setCount(count + 1) // ❌ 同样闭包问题
return <button onClick={clickFun}>{count}</button>
}
4 个问题
- 问题 1 — useState 初始化不响应 props 变化:
useState(() => props.initialCount ?? 0) 只在首次渲染执行。props 变化后 count 不会更新 → 需要加 useEffect 同步
- 问题 2 — useEffect 没有依赖数组:
useEffect(() => { ... }) 没有第二个参数 → 每次渲染都会执行,疯狂绑定事件监听
- 问题 3 — 事件监听没有清除:
addEventListener 没有 return cleanup → 内存泄漏
- 问题 4 — 闭包陷阱:
setCount(count + 1) 在事件监听回调中捕获了旧的 count → 应该用 setCount(prev => prev + 1)
修复版
function Component(props) {
const [count, setCount] = useState(() => props.initialCount ?? 0)
useEffect(() => {
setCount(props.initialCount ?? 0)
}, [props.initialCount])
useEffect(() => {
if (!props.shouldAddListener) return
const handler = () => setCount(prev => prev + 1)
window.addEventListener('click', handler)
return () => window.removeEventListener('click', handler)
}, [props.shouldAddListener])
return <button onClick={() => setCount(prev => prev + 1)}>{count}</button>
}