stateChange event fires once for each property in the state due to incorrect object.assign use
See original GitHub issueI implemented this code as written in https://css-tricks.com/build-a-state-management-system-with-vanilla-javascript/
I wanted to comment there, but the thread is closed.
Issue
I have say 12 properties in my state, and with each mutation, the whole state object gets replaced, thus the ‘stateChange’ event is getting fired 12 times.
Expected Behavior
Expected console.log output–
store.js:52 ACTION: changePage store.js:27 stateChange: currentPage: 1
Actual Behavior
Actual console.log output– ACTION: setLoadingState store.js:52 ACTION: changePage store.js:27 stateChange: currentPage: 1 store.js:27 stateChange: currentPage: 1 store.js:27 stateChange: lastPage: 0 store.js:27 stateChange: direction: down store.js:27 stateChange: isLoading: false store.js:27 stateChange: isGated: false store.js:27 stateChange: isChallenge: false store.js:27 stateChange: isLockedState: true store.js:27 stateChange: nickname: store.js:27 stateChange: showWave: false store.js:27 stateChange: challengePoints: 0 store.js:27 stateChange: challengePages: 3,5,7,10
Steps to Reproduce the Problem
- Add multiple properties to the state
- Subscribe to the ‘stateChange’ event
- Use the app in the browser and view console.log output
I can make a PR if we decide this change would be helpful.
Current Implementation
self.state = Object.assign(self.state, newState);
Solution: Start with an empty object for mutating the state.
self.state = Object.assign({}, self.state, newState);
this.setTrap(); // then call a method to re-init the set trap Proxy
Issue Analytics
- State:
- Created 5 years ago
- Reactions:2
- Comments:9 (5 by maintainers)
Right! I think @lospringliu was suggesting that we take out the object.asssign and just switch use a standard assignment instead.
Which off the top of my head is going to look like
self.state = newState;
This fixes the issue with the set trap Proxy, and does not require the Proxy be re-added.
The problem with Object.assign I think, is that when you have matching keys in the source object and the new object, Object.assign will use a setter on every matching key to update the values from the new object. newState is the whole state object, thus Object.assign triggers the proxy X number of times.
Is there any case or reason where we should stand up for merging with using Object.assign here?
the mutations return state, I think there is no need to merge states together using Object.assign, simply assign the returned state to the store state