简体   繁体   中英

State is changing on me inside mutation

I am having a really weird issue with state changing inside a mutation(!). In my mutation I am logging the following on the first two lines:

console.log('mutation state:', state)
console.log('mutation state.game.gameTree[2]:', state.game.gameTree[2]) 

Expected: that state.game.gameTree is the same

Actual: They are not! As you can see on the screenshot state.game.gameTree[2].activeActionId are not the same.

控制台日志

How can this value possibly change from line 1 to line 2? I hope someone can help :)

Chrome displays the value of an object at the time you view it in the console, not at the time it is logged. I would try doing this:

console.log('mutation state:', JSON.parse(JSON.stringify(state)))
console.log('mutation state.game.gameTree[2]:', JSON.parse(JSON.stringify(state.game.gameTree[2])))

And if you still get the same issue, then something weird is going on.

For example, if you had:

 function example() { var a = { b: { c: 1 }}; return function() { abc++; return a; } } var wtf = example() console.log(wtf()) console.log(wtf()) console.log(wtf()) 

You'll see here that it increments as expected. If you run it in chrome, you'll see:

{b: {…}}
{b: {…}}
{b: {…}}

and when you then expand it, they would all show the same value.

As dave already mentioned, if you hover over the i to the right of your expanded object, you will see that "it has been evaluated now". In other words, it will check what the value is at the time you expand it, not what the value is when it was logged.

If you need to debug something that is changing rapidly, use a debugger statement. This will pause execution and shows the debugger statement in your source. You can hover over variables to see their content, or find a variable in some scope on the right hand side. You can step through your code to see how your variables change. If you log something, since the execution has stopped, the object will actually be evaluated at the time it was logged if you do:

console.log(x);
debugger;

I found the cause. Thank you both for your suggestions. They were very helpful in guiding me in the right direction.

I was actually mutating the game object in a domain function that was expecting a simple data object. I have always considered my domain functions immutable since they all return new data objects using the spread operator. And coming from a functional framework based on immutable reactive streams this had never been a problem.

However, with Vue I realize that this can be problematic since Game is not longer a plain data object. I will have to look into how to deal optimally with this.

For now, using JSON.parse(JSON.stringify(state))) works. It converts game to a plain data object and everything works as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM