如果直接在Redux reducer中修改状态会发生什么?

时间:2017-05-03 11:42:25

标签: javascript redux immutability flux

我正在查看正在讨论以下减速器的Redux tutorial

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, completed: false
            }]);
        case 'TOGGLE_TODO':
            return state.map((todo, index) =>
                action.index === index ?
                    { text: todo.text, completed: !todo.completed } :
                    todo
            )
        default: return state;
    }
}

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

它清楚地表达了什么,但是我没有为什么它会使state.concat / state.map复制状态而不是直接处理它。我理解它是为了实现不变性,但从技术上讲,如果我改变代码可能会出错:

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

到此:

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

传递给减速器的状态无论如何已经过时了,所以无论它是否已被更改,都不能在任何地方使用(如果我没有弄错,那确实是Redux正在做的事情 - 它忽略了以前的状态,并把新的状态作为真​​理的来源")。因此,只有函数返回的新状态才重要。

因此,如果我遵循这种直接在reducer中修改状态并返回此方法的方法,那么在我的应用程序中可以创建什么错误?有什么想法吗?

3 个答案:

答案 0 :(得分:9)

Redux使用===将您的旧状态与新状态进行比较,以了解它是否已更改。如果您改变状态而不是创建新副本,则此测试将失败,您的组件将无法更新。

答案 1 :(得分:3)

Redux的核心并不关心不变性。它实际上也没有做任何事情来防止突变,无论是在减压器内还是在你的应用中的其他部分。但是,突变会破坏时间旅行调试,以及React-Redux connect功能。在Immutable Data上有一个Redux常见问题解答的新部分,它更详细地描述了Redux如何以及为何依赖于不变性,Why isn't my component re-rendering?上的问题也适用。

此外,我目前正在撰写一篇博客文章,讨论Redux实际需要的技术限制,以及打算使用Redux的方式可能的使用Redux。我希望在下周内发布这篇文章。如果您有兴趣,请关注我的博客http://blog.isquaredsoftware.com

答案 2 :(得分:0)

使用redux和action-reducers模式都是关于纯函数的。减速器应该是纯函数,这意味着它们不应该改变状态。纯函数接受输入并返回新输出。如果redux没有使用这种模式并且状态发生了变异,那么数据将是不可靠的,因此导致应用程序中出现错误,例如您的反应组件将无法更新。