最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - DeepCopy Object in JavaScript using immer - Stack Overflow

programmeradmin2浏览0评论

I am using immer to transform react/redux state. Can I also use immer to just deep copy an object without transforming it?

import produce, {nothing} from "immer"



const state = {
    hello: "world"
}

produce(state, draft => {})
produce(state, draft => undefined)
// Both return the original state: { hello: "world"}

This is from the official immer README. Does this mean that passing an empty function to produce returns a deep copy of the original state or actually the original state?

Thank you very much for your help :)!

I am using immer to transform react/redux state. Can I also use immer to just deep copy an object without transforming it?

import produce, {nothing} from "immer"



const state = {
    hello: "world"
}

produce(state, draft => {})
produce(state, draft => undefined)
// Both return the original state: { hello: "world"}

This is from the official immer README. Does this mean that passing an empty function to produce returns a deep copy of the original state or actually the original state?

Thank you very much for your help :)!

Share Improve this question asked Mar 5, 2019 at 9:08 AndreAndre 4,6255 gold badges23 silver badges33 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 18

This is easily testable with

import { produce } from 'immer'

const state = {
  hello: 'world',
}

const nextState = produce(state, draft => {})

nextState.hello = 'new world'
console.log(state, nextState)

which outputs

Object { hello: "new world" }

Object { hello: "new world" }

which means that it does NOT create a deep copy of an object.

UPDATE:

So I got interested and tested out the library a lot and here are my findings.

The code snippet I wrote above is simply an optimisation in the library which returns the old state if no changes are made. However, if you make some changes, then the library starts functioning as intended and the mutation later is made impossible. That is,

const state = {
  hello: 'world',
}

const nextState = produce(state, draft => {
  draft.hello = 'new world';
})

nextState.hello = 'newer world';

console.log(state, nextState)

will result in an error: TypeError: "world" is read-only

Which means that your newState is immutable and you can no longer perform mutations on it.

Another rather interesting thing I found is that immer fails when using class instances. That is,

class Cls {
  prop = 10;
}

const instance = new Cls();

const obj = {
  r: instance,
};

const newObj = produce(obj, draft => {
  draft.r.prop = 15;
});

console.log(obj, newObj);

results in

r: Object { prop: 15 }

r: Object { prop: 15 }

So to get back to the initial question, can you get a deep copy of the initial Object by changing nothing in the draft. No you cannot, and even if you did (by changing a property created just to fool immer perhaps), the resultant cloned object will be immutable and not really helpful.

Solution : The Immer's produce only provides a new deep cloned object on updation. you can create your own produce function that behaves just like that of immer's produce but gives a cloned object everytime using loadash

import _ from 'lodash';
export default function produceClone(object, modifyfunction) {
    let objectClone = _.cloneDeep(object);
    if (!modifyfunction) return objectClone;
    modifyfunction(objectClone);
    return objectClone;
    }

This will give you a deepCloned(or deep copied) object everytime, irrespective of whether you modify the object or not.

发布评论

评论列表(0)

  1. 暂无评论