我正在查看正在讨论以下减速器的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中修改状态并返回此方法的方法,那么在我的应用程序中可以创建什么错误?有什么想法吗?
答案 0 :(得分:9)
Redux使用===将您的旧状态与新状态进行比较,以了解它是否已更改。如果您改变状态而不是创建新副本,则此测试将失败,您的组件将无法更新。
答案 1 :(得分:3)
Redux的核心并不关心不变性。它实际上也没有做任何事情来防止突变,无论是在减压器内还是在你的应用中的其他部分。但是,突变会破坏时间旅行调试,以及React-Redux connect
功能。在Immutable Data上有一个Redux常见问题解答的新部分,它更详细地描述了Redux如何以及为何依赖于不变性,Why isn't my component re-rendering?上的问题也适用。
此外,我目前正在撰写一篇博客文章,讨论Redux实际需要的技术限制,以及打算使用Redux的方式
答案 2 :(得分:0)
使用redux和action-reducers模式都是关于纯函数的。减速器应该是纯函数,这意味着它们不应该改变状态。纯函数接受输入并返回新输出。如果redux没有使用这种模式并且状态发生了变异,那么数据将是不可靠的,因此导致应用程序中出现错误,例如您的反应组件将无法更新。