2

Let's say we have two objects:

const state = {
  fishes: { /* some obj data */ },
  animals: { /* some obj data  */ }

const animals = { /* some NEW data */ }

In Vuex there is a method replaceState(), which according to the documentation takes one argument and replaces the state with that object.

What will be the result of the following:

replaceState({ ...state, animals })

More specifically, what does { ...state, animals } do exactly?

To bring some context, I took this example from the answer of this question. In that question, the user wanted to replace the animals property of the state with the new object animals.

I'm not sure if this is relevant to Vuex / Vue.js, or is it a pure JS question, but I'll tag it with vue.js anyway.

TylerH
  • 19,065
  • 49
  • 65
  • 86
Nikolay Dyankov
  • 5,020
  • 9
  • 45
  • 64

3 Answers3

4

This is actually from ECMAScript 2018's spread syntax and ECMAScript 2015's object destructuring.

{ ...state, animals } creates a shallow copy of the state object, with a new property called animals (with the value of animals object within it).

Since you are a Vuex user, this conforms to the rule of immutable update patterns, which is to prevent the 'original' state object from being altered or mutated. You should read up on the ways of handling common operations such as add/update/delete, using the immutable pattern.

TylerH
  • 19,065
  • 49
  • 65
  • 86
wentjun
  • 27,425
  • 7
  • 54
  • 65
  • Just fyi, array spread is not same as Object spread. Object spread is a part of ES7 and while array spread is of ES6 – Rajesh Apr 15 '19 at 08:37
  • @Rajesh Thanks for pointing that out! It does indeed get confusing at times since spread applies for both objects and arrays after the proposals. – wentjun Apr 15 '19 at 08:46
  • "with a new property called animals" - but if the state object already contains a property animals, will it get overwritten? Also, doesn't the destructuring result in multiple parameters passed to the replaceState() function in my example? – Nikolay Dyankov Apr 15 '19 at 08:47
  • @NikolayDyankov yes, I believe it does. It in facts create a shallow copy from the 'original' state object. You can try testing it out by mutating the copied object and run console.log() on both of them to see the differences! – wentjun Apr 15 '19 at 08:49
  • However, I have to bring your attention to the fact that, if `animals` is a nested object, you will have to shallow copy the various levels of it. This link has an excellent example https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns#correct-approach-copying-all-levels-of-nested-data . I hope I am not boring you too much with all these URLs, but it is essential for you to understand this important concept. – wentjun Apr 15 '19 at 08:54
  • I can try to have the animals object only one layer deep, but I will need to have arrays for a value of a property eventually, and that will need deep cloning of the animals object. As far as I'm aware, arrays are also objects and references are kept in a shallow copy of the parent object. Correct? – Nikolay Dyankov Apr 15 '19 at 09:02
  • @NikolayDyankov yes, precisely. If you are updating a specific item in the array, you will need to return that updated item (the item you want to update), and the other existing items in the array. – wentjun Apr 15 '19 at 09:08
2

It means Object.assign({}, state, { animals: animals} }.

mbojko
  • 9,720
  • 1
  • 10
  • 20
2

What is does is it spreads all the properties of state into the new object - making a shallow copy. All the properties in the original object (state) will be copied into the new object (the one you're passing into replaceState). Here's a simple demonstration:

let obj1 = { obj: "1" };
let obj2 = { ...obj1, obj2: true };
console.log(obj1);
console.log(obj2);

The animals bit is ES6 property shorthand, and will essentially do this:

animals: animals

It's just cleaner syntax.

Jack Bashford
  • 38,499
  • 10
  • 36
  • 67