# Immer

URL: https://caijiao.org/immer/guide/introduction
Source: docs/immer/guide/introduction.md
Description: 了解 Immer 库的基本概念和优势，以及如何开始使用它来简化不可变状态管理。

2019 年 “年度突破”[React 开源奖](https://osawards.com/react/)和“最有影响的贡献”[JavaScript 开源奖](https://osawards.com/javascript/)的获得者

- 介绍博客: [Immer: Immutability the easy way](https://medium.com/@mweststrate/introducing-immer-immutability-the-easy-way-9d73d8f71cb3)
- Egghead.io 简短课程，涵盖 Immer 的基本知识: [Simplify creating immutable data trees with Immer (7 分钟)](https://egghead.io/lessons/redux-simplify-creating-immutable-data-trees-with-immer)
- Egghead.io 免费深入课程: [Immutable JavaScript Data Structures with Immer (58 分钟)](https://egghead.io/courses/immutable-javascript-data-structures-with-immer)

## 什么是 Immer?

Immer (德语中的意思是 "总是") 是一个微型包，允许你使用更方便的方式来处理不可变状态。它基于 [copy-on-write](https://en.wikipedia.org/wiki/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 的基本原理](/images/immer/immer.png)

这个过程中，Immer 使用了 [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) 对象来跟踪对草稿的所有修改，然后生成一个全新的不可变状态树，同时尽可能地与原始状态共享未修改的部分。

## 优势

- **简洁的代码**：不需要编写繁琐的展开操作符
- **易于阅读**：代码更直观地反映了意图
- **减少错误**：降低了因手动展开对象而导致的错误
- **结构共享**：与手动编写的不可变更新一样高效
- **类型安全**：与 TypeScript 和 Flow 完美配合

## 用例

Immer 可以在任何需要处理不可变数据的地方使用：

- React 和 React Native 状态管理
- Redux 和其他状态容器
- MobX
- 任何需要不可变性的 JavaScript 应用

无论你是在构建大型复杂应用还是小型项目，Immer 都可以帮助你编写更简洁、更可维护的代码。
