john
john

Reputation: 21

Object.assign behavior in this case

Why in such case,

var a={b:1};
Object.assign(a,{b:a.b+2},{b:a.b+4});

console.log(a);

The result of assign is object

{b: 5}

Rather than

{b: 7}

For the record using this I was trying to explain why value is 1 in below code

// assuming this.state = { value: 0 };
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});

Upvotes: 2

Views: 87

Answers (3)

Ryan H.
Ryan H.

Reputation: 7844

Object.assign and React's setState work differently. For Object.assign, you can think of it as a right-to-left merge of the objects:

Object.assign(a,{b:a.b+2},{b:a.b+4});
Object.assign(a,{b:3},{b:5});
Object.assign(a,{b:5});

However, setState is a different story. It is an asynchronous operation. In your case, you're simply executing the exact same statement three times:

this.setState({ value: 0 + 1});
this.setState({ value: 0 + 1});
this.setState({ value: 0 + 1});

Multiple setState calls can update state in one event loop and result in a single re-render. Part of the architectural efficiency behind the way setState works may be responsible for this behaviour. This reference may also be helpful:

Why is setState giving me the wrong value?

If you want to use the previous value of a setState operation, you can do somthing like this:

setState((prevState) => ({ value: prevState.value + 1 }));

or

setState({ value: this.state.value + 1 }, () => {
    // In here, the state has been updated
});

However, it's hard to give a precise practical solution as your example is contrived and there would probably be no practical need to do sequential setState operations like that.

See the React documentation for more details on setState.

Upvotes: 0

slesh
slesh

Reputation: 2007

It's expected a result. Because of Object.assign not sum values, but overwrite. It set values from right to left. The right value is {b: a.b+4} => {b: 5}. This value overlapse other ones.

Upvotes: 0

Bergi
Bergi

Reputation: 664599

Because arguments are evaluated before being passed to the function. You're basically doing

var a = {b: 1},
    tmp1 = {b: a.b+2}, // {b: 1+2}
    tmp2 = {b: a.b+4}; // {b: 1+4}
Object.assign(a, tmp1, tmp2);

You would need to do

var a = {b: 1};
Object.assign(a, {b: a.b+2}); // simpler: a.b += 2
Object.assign(a, {b: a.b+4}); // simpler: a.b += 4

to get 7.

Upvotes: 4

Related Questions