admin管理员组

文章数量:1241157

I'm looking at this Redux tutorial where the following reducer is being discussed:

function visibilityFilter(state = 'SHOW_ALL', action) {
    return action.type === 'SET_VISIBILITY_FILTER' ?
        action.filter :
        state
}

function todos(state = [], action) {
    switch (action.type) {
        case 'ADD_TODO':
            return state.concat([{
                text: action.text, pleted: false
            }]);
        case 'TOGGLE_TODO':
            return state.map((todo, index) =>
                action.index === index ?
                    { text: todo.text, pleted: !todopleted } :
                    todo
            )
        default: return state;
    }
}

function todoApp(state = {}, action) {
    return {
        todos: todos(state.todos, action),
        visibilityFilter: visibilityFilter(state.visibilityFilter, action)
    };
}

What it does it clear, however I don't get why it does the state.concat / state.map to duplicate the state instead of working on it directly. I understand it's to achieve immutability, but, technically, what could go wrong if I change the code from this:

return state.map((todo, index) =>
    action.index === index ?
        { text: todo.text, pleted: !todopleted } :
        todo
)

to this:

state[action.index]pleted = !state[action.index]pleted;
return state;

The state that was passed to the reducer is obsolete anyway, so whether it has been changed or not it must not be used anywhere (and if I'm not mistaken that's indeed what Redux is doing - it ignores the previous state and takes the new one as the "source of truth"). So only the new state returned by the function should matter.

So if I follow this approach of modifying the state directly in the reducer and returning this, what bug could that create in my application? Any idea?

I'm looking at this Redux tutorial where the following reducer is being discussed:

function visibilityFilter(state = 'SHOW_ALL', action) {
    return action.type === 'SET_VISIBILITY_FILTER' ?
        action.filter :
        state
}

function todos(state = [], action) {
    switch (action.type) {
        case 'ADD_TODO':
            return state.concat([{
                text: action.text, pleted: false
            }]);
        case 'TOGGLE_TODO':
            return state.map((todo, index) =>
                action.index === index ?
                    { text: todo.text, pleted: !todo.pleted } :
                    todo
            )
        default: return state;
    }
}

function todoApp(state = {}, action) {
    return {
        todos: todos(state.todos, action),
        visibilityFilter: visibilityFilter(state.visibilityFilter, action)
    };
}

What it does it clear, however I don't get why it does the state.concat / state.map to duplicate the state instead of working on it directly. I understand it's to achieve immutability, but, technically, what could go wrong if I change the code from this:

return state.map((todo, index) =>
    action.index === index ?
        { text: todo.text, pleted: !todo.pleted } :
        todo
)

to this:

state[action.index].pleted = !state[action.index].pleted;
return state;

The state that was passed to the reducer is obsolete anyway, so whether it has been changed or not it must not be used anywhere (and if I'm not mistaken that's indeed what Redux is doing - it ignores the previous state and takes the new one as the "source of truth"). So only the new state returned by the function should matter.

So if I follow this approach of modifying the state directly in the reducer and returning this, what bug could that create in my application? Any idea?

Share Improve this question edited May 3, 2017 at 11:55 laurent asked May 3, 2017 at 11:42 laurentlaurent 90.8k82 gold badges309 silver badges441 bronze badges 1
  • This answer explains in details http://stackoverflow./questions/35970515/how-is-state-immutability-actually-used-in-redux – neetesh Commented May 3, 2017 at 11:57
Add a ment  | 

3 Answers 3

Reset to default 14

Redux pares your old state to your new state with === to know if it changed. If you mutate the state instead of creating a new copy, this test will fail and your ponents won't update.

The core of Redux does not care about immutability. It also does not actually do anything to prevent mutations, either inside reducers or in other partso f your application. However, mutations will break time-travel debugging, as well as the React-Redux connect function. There's a new section of the Redux FAQ on Immutable Data that describes in more detail how and why Redux relies on immutability, and the question on Why isn't my ponent re-rendering? also applies.

Also, I'm currently working on a blog post that will discuss what technical limitations Redux actually requires, vs how you are intended to use Redux, vs how it's possible to use Redux. I'm hoping to have that post up within the next week. If you're interested, keep an eye on my blog at http://blog.isquaredsoftware..

Working with redux and the action-reducers pattern is all about pure functions. Reducers should be pure functions, which means that they should not mutate the state. Pure functions take an input and return a new output. In case redux didn't use this pattern and the state was mutated then the data would be unreliable and as result cause bugs in your application for example your react ponents would not get updated.

本文标签: javascriptWhat could happen if modifying state directly inside a Redux reducerStack Overflow