Redux状态是否会不同步?快速重复点击组件会导致状态过时吗?
关于连续点击Sorter组件时redux_state_obj是否过时的问题
先贴出组件代码:
function Sorter({ redux_state_obj, set }) { const handle_click = () => { const new_state = JSON.parse(JSON.stringify(redux_state_obj)) // update new_state based on redux_state_obj set(new_state) } return <div onClick={handle_click}>button</div> }
问题
假设极速连续点击上述Sorter组件,第二次点击时的redux_state_obj是否会过时,即使用的是第一次点击更新前的redux_state_obj?
回答
会过时,核心原因是JavaScript闭包的特性:
- 组件每次渲染时,都会生成一个新的
handle_click函数,这个函数会捕获当前渲染时刻的redux_state_obj值。 - 当极速连续点击时,第一次点击触发
set更新状态,但React的状态更新是异步批量处理的,组件还没来得及重新渲染生成新的handle_click,第二次点击调用的还是旧渲染周期里的handle_click,里面的redux_state_obj自然还是第一次点击前的旧值。 - 举个实际场景:假设初始
redux_state_obj是{ count: 0 },第一次点击把count改成1,但组件没完成重新渲染,第二次点击的handle_click拿到的还是{ count: 0 },更新后会基于0修改,直接覆盖第一次的更新结果。
解决方法
改用函数式更新,让set接收一个函数作为参数,这个函数的参数是当前最新的状态,这样不管什么时候调用,都能拿到最新的状态值:
const handle_click = () => { set(prevState => { const new_state = JSON.parse(JSON.stringify(prevState)) // 在这里基于prevState更新new_state return new_state }) }
这样每次触发更新时,都会用最新的状态来计算新值,彻底避免闭包导致的过时值问题。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

