Immer
2019 年 “年度突破”React 开源奖和“最有影响的贡献”JavaScript 开源奖的获得者
- 介绍博客: Immer: Immutability the easy way
- Egghead.io 简短课程,涵盖 Immer 的基本知识: Simplify creating immutable data trees with Immer (7 分钟)
- Egghead.io 免费深入课程: Immutable JavaScript Data Structures with Immer (58 分钟)
什么是 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 的基本原理是:
- 你有一个基础状态
- 你创建了一个该状态的草稿(draft)
- 你在草稿上进行任意的修改
- Immer 基于草稿的修改创建了一个全新的不可变状态

这个过程中,Immer 使用了 Proxy 对象来跟踪对草稿的所有修改,然后生成一个全新的不可变状态树,同时尽可能地与原始状态共享未修改的部分。
优势
- 简洁的代码:不需要编写繁琐的展开操作符
- 易于阅读:代码更直观地反映了意图
- 减少错误:降低了因手动展开对象而导致的错误
- 结构共享:与手动编写的不可变更新一样高效
- 类型安全:与 TypeScript 和 Flow 完美配合
用例
Immer 可以在任何需要处理不可变数据的地方使用:
- React 和 React Native 状态管理
- Redux 和其他状态容器
- MobX
- 任何需要不可变性的 JavaScript 应用
无论你是在构建大型复杂应用还是小型项目,Immer 都可以帮助你编写更简洁、更可维护的代码。