React 开发中,数据是不可变的。改 state 和 props,是用新的状态去替换旧的状态。改嵌套比较深的数据时,代码会比较复杂,可读性差。如:

  1. const { stu } = this.state
  2. this.setState(
  3. stu: {
  4. ...stu,
  5. info: {
  6. ...stu.info,
  7. age: stu.info.age + 1
  8. }
  9. }
  10. )

用 Immer 可以容易的处理不可变数据,提升代码可读性。

介绍

Immer (German for: always) is a tiny package that allows you to work with immutable state in a more convenient way. It is based on the copy-on-write mechanism.

Immer 是处理不可变数据的工具库。Immer 会为要改动的数据,生成一份拷贝。数据操作时,直接改拷贝的数据。最后,把改过的拷贝做为新的数据。

how-to-work.png

用 Immer 重构上面的代码,如下:

  1. import produce from "immer"
  2. const { stu } = this.state
  3. const newStu = produce(stu, draft => {
  4. draft.info.age = draft.info.age + 1
  5. })
  6. this.setState({
  7. stu: newStu
  8. })

Immer 也支持 Currying(柯里化,部分求值)。调用 produce 时,传入第一个参数是函数(数据处理函数)时,返回的是数据处理函数的函数。如:

  1. // 绑定数据处理函数
  2. const mapper = produce((draft, index) => {
  3. draft.index = index
  4. })
  5. // 使用
  6. console.dir([{}, {}, {}].map(mapper))
  7. // 输出: [{index: 0}, {index: 1}, {index: 2}])

为了方便在函数组件中使用 Immer,Immer 也提供了 React hook 库: use-immer

  1. import { useImmer } from "use-immer"
  2. const [stu, setStu] = useImmer({...});
  3. setStu(draft => {
  4. draft.info.age = draft.info.age + 1
  5. })

感觉不错吧,在项目中用起来吧~

参考文档