immer

376 阅读1分钟

1. 介绍

immer 是 mobx 的作者写的一个 immutable 库,核心实现是利用 ES6 的 proxy。

官网地址: github.com/immerjs/imm…

2. 简单实现

如何模拟一个超级简单的 produce, 代码如下:

function produce(state, thunk) {var stateCopy = { ...state };let copyTarget;stateCopy.a = new Proxy(state.a, {set(target, prop, val) {copyTarget = { ...target };copyTarget[prop] = val;},});thunk(stateCopy);stateCopy.a = copyTarget;return stateCopy;}const target = produce(state, (draftState) => {draftState.a.b = 2;});// 输出 1 和 2console.log(state.a.b, target.a.b);

3. 例子

1. 使用 redux 的时候, 我们修改引用类型比较麻烦, 比如我要在obj.a.c 插入一个数据 "3"

var obj = {a: {b: 1, c: [1,2]}};var newObj = {...obj,a: {...obj.a,c: [...obj.a.c, 3] // 或者 obj.a.c.slice().concat(3)}}// 若使用 immerimport produce from 'immer';var newObj = produce(obj, draft => {draft.a.c.push(3);});

2. umijs 里如何开启, 修改 .umirc.js

export default {  plugins: [    [      'umi-plugin-react',      {        antd: true,        dva: {          immer: true,        },      },    ],  ],};

修改目录 models 里的文件 history.js:

export default {  namespace: 'history',  state: {    a: {      b: 1    }  },  reducers: {    searchVal(state, { payload }) {      state.a.b = 10;    },  },  effects: {       },};

3. 由于它是用了 proxy, 所以如果层级嵌套比较深的话,可能有性能问题,建议 umijs 不要开启 dva, 而是在单独的 reducer 里面引入 immer, 然后修改 state。

export default {  namespace: 'history',  state: {    a: {      b: 1    }  },  reducers: {    searchVal(state, { payload }) {      state.a.b = 10;    },  },  effects: {       },};