如何使用Immer基于前一次状态更新React组件的state
React中结合Immer使用setState更新函数的实现方案
核心解决方案
将produce方法嵌套在setState的更新回调中,即可同时访问到React官方保证的最新前序状态,以及Immer提供的可变草稿代理:
handleClick(clickedOption) { this.setState(prevState => produce(prevState, draft => { // 用原始前序状态做索引查找,结果准确 const index = prevState.fooBar.selectedOptions.indexOf(clickedOption); if (index > -1) { draft.fooBar.selectedOptions.splice(index, 1); } else { draft.fooBar.selectedOptions.push(clickedOption); } })); }
方案说明
- 外层
setState传入的更新回调接收的prevState是React官方保证的最新前序状态,完全规避直接读取this.state可能出现的状态过期问题 prevState是未被代理的原始状态对象,执行indexOf、等值对比等操作返回的结果完全准确- 所有状态修改仍然操作
draft代理,Immer会自动生成符合不可变规范的新状态返回给setState,无需手动处理嵌套对象的解构拷贝
替代方案:使用Immer内置original工具函数
如果偏好Immer的柯里化写法,可以直接调用Immer提供的original方法获取草稿对应的原始状态:
首先导入original:
import { produce, original } from 'immer';
修改后的状态更新代码:
handleClick(clickedOption) { this.setState(produce(draft => { // 获取草稿对应的原始状态数组 const originalOptions = original(draft.fooBar.selectedOptions); const index = originalOptions.indexOf(clickedOption); if (index > -1) { draft.fooBar.selectedOptions.splice(index, 1); } else { draft.fooBar.selectedOptions.push(clickedOption); } })); }
方案说明
original是Immer官方提供的工具方法,用于返回代理草稿对应的原始状态值,用它执行对比、查找类操作结果完全准确。
内容的提问来源于stack exchange,提问作者Fateh Khalsa
相关产品推荐
相关产品推荐

