教程 immer tutorial

Immer

2019 年 “年度突破”React 开源奖和“最有影响的贡献”JavaScript 开源奖的获得者

什么是 Immer?

Immer (德语中的意思是 “总是”) 是一个微型包,允许你使用更方便的方式来处理不可变状态。它基于 copy-on-write 机制。

使用 Immer,你可以通过 简单地修改草稿状态 来创建不可变状态。Immer 将负责为你计算下一个不可变状态,并使用结构共享。

动机

对不可变数据结构的操作可以非常简单。例如,获取数组中的第一个元素不需要任何特殊的 API:

javascript
const firstTodo = todos[0]

同样,添加一个新的 todo 也很简单:

javascript
const newTodos = [...todos, newTodo]

但是,当我们需要更新嵌套在对象树深处的某个对象时,事情会变得非常复杂:

javascript
const nextState = {
 ...state,
 profile: {
  ...state.profile,
  name: {
   ...state.profile.name,
   firstName: 'Michel'
  }
 }
}

这是繁琐的,容易出错的,而且很难阅读。

Immer 解决了这个问题,允许你使用简单的 JavaScript 赋值来修改状态:

javascript
const nextState = produce(state, draft => {
 draft.profile.name.firstName = 'Michel'
})

工作原理

Immer 的基本原理是:

  1. 你有一个基础状态
  2. 你创建了一个该状态的草稿(draft)
  3. 你在草稿上进行任意的修改
  4. Immer 基于草稿的修改创建了一个全新的不可变状态
Immer 的基本原理
Immer 的基本原理

这个过程中,Immer 使用了 Proxy 对象来跟踪对草稿的所有修改,然后生成一个全新的不可变状态树,同时尽可能地与原始状态共享未修改的部分。

优势

  • 简洁的代码:不需要编写繁琐的展开操作符
  • 易于阅读:代码更直观地反映了意图
  • 减少错误:降低了因手动展开对象而导致的错误
  • 结构共享:与手动编写的不可变更新一样高效
  • 类型安全:与 TypeScript 和 Flow 完美配合

用例

Immer 可以在任何需要处理不可变数据的地方使用:

  • React 和 React Native 状态管理
  • Redux 和其他状态容器
  • MobX
  • 任何需要不可变性的 JavaScript 应用

无论你是在构建大型复杂应用还是小型项目,Immer 都可以帮助你编写更简洁、更可维护的代码。