最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Does JSON.parse(JSON.stringify(state)) guarantee no mutation of redux state? - Stack Overflow

programmeradmin2浏览0评论

I've been tracking down an issue where a redux store correctly updates, but the ponent does not reflect the change. I've tried multiple ways of making sure I'm not mutating the state, however the issue persists. My reducers monly take the form:

case 'ADD_OBJECT_TO_OBJECT_OF_OBJECTS': {
    newState = copyState(state);
    newState.objectOfObjects[action.id] = action.obj;
    return newState;
}

For my copyState function, I usually use nested Object.assign() calls, but avoiding errors isn't so straightforward. For testing, to make sure I'm not mutating state, is it correct to use

const copyState = (state) => {
    return JSON.parse(JSON.stringify(state));
};

as a guaranteed method of not mutating (redux) state, regardless of how expensive the process is?

If not, are there any other deep copy methods that I can rely on for ensuring I'm not mutating state?

EDIT: Considering that other people might be having the same issue, I'll relay the solution to the problem I was having.

I was trying to dispatch an action, and then in the line after, I was trying to access data from the store that was updated in the previous line.

dispatchAction(data) // let's say this updates a part of the redux state called 'collection'
console.log(this.props.collection) // This will not be updated!

Refer to

I've been tracking down an issue where a redux store correctly updates, but the ponent does not reflect the change. I've tried multiple ways of making sure I'm not mutating the state, however the issue persists. My reducers monly take the form:

case 'ADD_OBJECT_TO_OBJECT_OF_OBJECTS': {
    newState = copyState(state);
    newState.objectOfObjects[action.id] = action.obj;
    return newState;
}

For my copyState function, I usually use nested Object.assign() calls, but avoiding errors isn't so straightforward. For testing, to make sure I'm not mutating state, is it correct to use

const copyState = (state) => {
    return JSON.parse(JSON.stringify(state));
};

as a guaranteed method of not mutating (redux) state, regardless of how expensive the process is?

If not, are there any other deep copy methods that I can rely on for ensuring I'm not mutating state?

EDIT: Considering that other people might be having the same issue, I'll relay the solution to the problem I was having.

I was trying to dispatch an action, and then in the line after, I was trying to access data from the store that was updated in the previous line.

dispatchAction(data) // let's say this updates a part of the redux state called 'collection'
console.log(this.props.collection) // This will not be updated!

Refer to https://github./reactjs/redux/issues/1543

Share Improve this question edited May 6, 2017 at 22:51 underscore asked May 6, 2017 at 9:25 underscoreunderscore 2854 silver badges10 bronze badges 2
  • state will be untouched in copyState – Jaromanda X Commented May 6, 2017 at 9:30
  • It would be possible (but incredibly dumb) to give state a .toJSON method that mutates it. – Bergi Commented May 6, 2017 at 12:32
Add a ment  | 

2 Answers 2

Reset to default 3

Yes this does a deep clone, regardless of how expensive it is. The difficulty (as hinted in ment under the question) is to make sure state stays untouched everywhere else.

Since you're asking for other approaches, and that would not fit in a ment, I suggest to take a look at ImmutableJS, which eliminates the issue of tracking state mutation bugs (but might e with its own limitations):

const { Map } = require('immutable')
const map1 = Map({ a: 1, b: 2, c: 3 })
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50

Your copyState() function will NOT mutate your state. It is fine. And for others reading this question, it is also fine to directly go

const newState = JSON.parse(JSON.stringify(oldState));

to get a deep copy. Feels unclean, but it is okay to do.

The reason you're not seeing your subscriptions run may be that Redux pares the new state (the output of the reducer function) to the existing state before it copies it. If there are no differences, it doesn't fire any subscriptions. Hence the reason that we never mutate state directly but return a copy -- if we did mutate state, changes would never be detected.

Another reason might be that we don't know what dispatchAction() in your code does exactly. If it is async (maybe because of middleware?) the changes wouldn't be applied until after your console.log() on the next line.

发布评论

评论列表(0)

  1. 暂无评论