-1

Is the state below mutated by the second line?

let state = { a: 1, b: 2, c: 3 };
state = { ...state, c: 4 };

It should be making a copy of the state as the following shows and so it should not be mutating e.g.

let state = { a: 1, b: 2, c: 3 };
let old = state;

state = { ...state, c: 4 };
let newState = state;

console.log(old);
console.log(newState);

With the following output for each console logs

{a: 1, b: 2, c: 3}

{a: 1, b: 2, c: 4}

Is this ok to be used in the context of React setState?

Community
  • 1
  • 1
rnk
  • 2,394
  • 1
  • 19
  • 19
  • 2
    `new` is a reserved word in JS https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords – Roko C. Buljan Apr 01 '18 at 23:13
  • 1
    Other than the `new` keyword (rename that var to something else), everything seems OK. Haven't you tried it? – acdcjunior Apr 01 '18 at 23:26

3 Answers3

1

If you're unclear how Javascript treats objects as references, take a look here.

To answer the first part of the question, no, state is not being mutated. I think in regards to React you are aware that you shouldn't modify a components state directly, e.g

this.state.foo = 'bar'

because React won't know that you've modified it and therefore won't trigger a render cycle.

The components setState method should be used, and will shallow merge properties, so:

this.setState({ c: 4 })

Will modify your initial state such that:

{
  a: 1,
  b: 2,
  c: 4,
}

So, there is no need for you to create your own mutated copy of state before calling setState.

Dave Meehan
  • 3,133
  • 1
  • 17
  • 24
0

No, it is not being mutated. It is being reassigned as a new object. It's creating a copy with references to the previous state. Think of it the same way as concat.

let arr = [1,2]
arr = arr.concat([2])

This is not a mutation of arr. It is a new array that you've decided to overwrite the previous variable with.

Andrew
  • 7,201
  • 5
  • 25
  • 34
-1

As pointed in the comments, your problem might stem simply from the use of an illegal reserved keyword (new).

Other than that here is an explanation of what is going on when manipulating object references in your code sample:

let state = { a: 1, b: 2, c: 3 };

let old = state; // the variable named "old" points (in memory)
                 // to the same reference as the variable named "state"
                 // (let's call this content "object A").
                 // If the common content they refer to is modified
                 // via the use of either variable,
                 // the same (unique) memory space is modified.

state = { ...state, c: 4 }; // Now the variable named "state"
                            // points to a new object (let's call this content "object B"),
                            // that was just created using the literal object notation. 
let newState = state; // the new variable named "newState"
                      // points to the same object as the variable
                      // named "state": "object B".

console.log(old); // displays object A
console.log(newState); // displays object B
Sébastien
  • 11,860
  • 11
  • 58
  • 78
  • Your example doesn't run (due to use of object spread) and the comments added are hard to follow and inaccurate to the code. – Dave Meehan Apr 02 '18 at 13:50
  • Thanks for pointing the error in the comments, I fixed it. I do not think they are hard to follow but I would like to know what you find unclear (now that the mistake is corrected). – Sébastien Apr 02 '18 at 15:49
  • Regarding the code, it does run but of course only in browsers that support the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Browser_compatibility). – Sébastien Apr 02 '18 at 15:52
  • Really only that it was a bit verbose and the typo was confusing. It's largely repeating other Q/A's on the subject of javascripts reference vs value implementation, so doesn't need restating. You still have a confusingly named link, the fact the snippet doesn't work in most major browsers should at least be mentioned, or novices can't work out if the code is a valid solution. Personally I'd convert from the snippet syntax to just a code block. Object spread is an experimental feature. – Dave Meehan Apr 02 '18 at 15:55
  • OK, thanks again for pointing out the link. Regarding the spread operator, I think most SO users do not use IE/edge, and given that it is part of the OP's question, I think these present comments (including my link to MDN) will suffice to alert the few who don't know what it means. – Sébastien Apr 02 '18 at 16:00
  • It doesn't work in Safari either, so that's excluding a pretty big chunk of peoples user experience. Also, given that many users here are novices how are they supposed to navigate that? Ok, the OP used it, so probably understands, but the purpose of SO is to help those that come along later too. It's a shame that SO's Snippet runner doesn't produce useful error messages either. I query whether the Snippet runner is needed as the output can be just shown - the interactivity is largely redundant. – Dave Meehan Apr 02 '18 at 16:20