immerjs / immer

Create the next immutable state by mutating the current one
https://immerjs.github.io/immer/
MIT License
27.73k stars 850 forks source link

produce mutates the original value #606

Closed TheILPlace closed 4 years ago

TheILPlace commented 4 years ago

๐Ÿ› Bug Report

using in Angular9. creating a new instance of an object based on a class. setting it's value. now using immer to produce a new state object. the original object is also mutated to match the new state

reproduction https://stackblitz.com/edit/angular-ivy-frogd8?file=src%2Fapp%2Fapp.component.ts

steps:

export class State { name: string; }

const orig: State = new State(); orig.name = 'my name';

const newState = produce(orig, draft => { draft.name = 'new name'; })

console.log(orig, newState); console.log('equal', orig==newState)

in the console, the orig object also has the name property as 'new name'; and the orig and newState are equal !

solving this is done by creating the original state as: const orig: State = {...new State()};

why using a new instance of an object as the original state doesnt work ? and i need to spread it into a new object ? is this a bug ?

mweststrate commented 4 years ago

Please check the docs on how to use immer on complex objects like classes.

On Tue, 26 May 2020, 21:55 TheILPlace, notifications@github.com wrote:

๐Ÿ› Bug Report

using in Angular9. creating a new instance of an object based on a class. setting it's value. now using immer to produce a new state object. the original object is also mutated to match the new state

reproduction

https://stackblitz.com/edit/angular-ivy-frogd8?file=src%2Fapp%2Fapp.component.ts

steps:

export class State { name: string; }

const orig: State = new State(); orig.name = 'my name';

const newState = produce(orig, draft => { draft.name = 'new name'; })

console.log(orig, newState); console.log('equal', orig==newState)

in the console, the orig object also has the name property as 'new name'; and the orig and newState are equal !

solving this is done by creating the original state as: const orig: State = {...new State()};

  • Immer version: 6.0.8

why using a new instance of an object as the original state doesnt work ? and i need to spread it into a new object ? is this a bug ?

โ€” You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/immerjs/immer/issues/606, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN4NBBHTZUXDJOEXISDASTRTQUDVANCNFSM4NLEMOCA .

raphaelbs commented 4 years ago

Hi, I'm facing the same issue.

Please check this codesandbox demo. It is not using any special structure, just a plain JS object and the initial state object is being mutated.

mweststrate commented 4 years ago

That one always overwrites the draft with the initial state. To use a curried producer with initial state see the docs page on curried reducers.

Op vr 29 mei 2020 21:21 schreef Raphael Brandรฃo notifications@github.com:

Hi, I'm facing the same issue.

Please check this codesandbox demo https://codesandbox.io/s/immer-mutating-initial-state-c6xuq?file=/index.test.js. It is not using any special structure, just a plain JS object and the initial state object is being mutated.

โ€” You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/immerjs/immer/issues/606#issuecomment-636174669, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAN4NBAE7OOUMZ6LKHXWMFDRUAKMXANCNFSM4NLEMOCA .

raphaelbs commented 4 years ago

Oh, I'm feeling dumb right now :smile: Thanks! Immer is awesome!