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: { },};