如果直接在 Redux reducer 中修改状态会发生啥?
Posted
技术标签:
【中文标题】如果直接在 Redux reducer 中修改状态会发生啥?【英文标题】:What could happen if modifying state directly inside a Redux reducer?如果直接在 Redux reducer 中修改状态会发生什么? 【发布时间】:2017-10-01 05:28:36 【问题描述】:我正在查看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;
传递给 reducer 的状态无论如何都是过时的,所以无论它是否已被更改,它都不能在任何地方使用(如果我没记错的话,这确实是 Redux 正在做的事情 - 它忽略了之前的状态并将新的作为“真相的来源”)。所以只有函数返回的新状态才重要。
因此,如果我按照这种方法直接在 reducer 中修改状态并返回它,那会在我的应用程序中创建什么错误?有什么想法吗?
【问题讨论】:
这个答案详细解释http://***.com/questions/35970515/how-is-state-immutability-actually-used-in-redux 【参考方案1】:Redux 使用 === 将旧状态与新状态进行比较,以了解它是否发生了变化。如果您改变状态而不是创建新副本,则此测试将失败并且您的组件将不会更新。
【讨论】:
谢谢,我认为这是关键,Redux 比较通过 reducer 发送前后状态的方式。如果是进行深度比较,我们就不需要关心这个了。我觉得这实际上有点抽象,但出于性能原因,这是必要的。 我不认为这是一个泄漏的抽象。不可变编程是一种众所周知的范式,并且在 JS 社区中获得了更多的关注。 我对此并不完全确定。这里(以及其他地方,以及我读过的任何内容)都没有人可以解释如果状态改变会引入什么错误,然后从减速器内部返回。好的,原因是 Redux 正在做的 ===,这是一种优化。但是,如果它进行深度比较,那么不变性就没有意义了。话虽如此,也许我错过了什么。 我还要说,直接更新状态会使反向重播应用程序变得困难,并且在分派给定操作之前清楚地看到状态是什么。我的假设也正确吗?【参考方案2】:Redux 的核心并不关心不变性。它实际上也没有做任何事情来防止突变,无论是在减速器内部还是在应用程序的其他部分。然而,突变会破坏时间旅行调试,以及 React-Redux connect
函数。 Immutable Data 上的 Redux 常见问题解答中有一个新部分更详细地描述了 Redux 如何以及为什么依赖于不变性,Why isn't my component re-rendering? 上的问题也适用。
另外,我目前正在撰写一篇博文,讨论 Redux 实际需要哪些技术限制,以及您打算如何使用 Redux,以及它如何可能 使用 Redux。我希望在下周内发布该帖子。如果您有兴趣,请关注我的博客http://blog.isquaredsoftware.com。
【讨论】:
【参考方案3】:使用 redux 和 action-reducers 模式都是关于纯函数的。 Reducer 应该是纯函数,这意味着它们不应该改变状态。纯函数接受一个输入并返回一个新的输出。如果 redux 没有使用这种模式并且状态发生了变化,那么数据将不可靠,从而导致应用程序中的错误,例如您的反应组件不会得到更新。
【讨论】:
如果我们知道我们在做什么。这应该不是问题。一个例子是当我们想将 redux 用作全局存储时。想象一棵树,它可以长到任何大小。每次完全复制它都会对性能造成很大影响,我们可以对其进行变异。而且我们从不直接使用它来更新我们的组件。我们通过强制重新渲染来触发更新时的重新渲染。为此类极端情况提供此类功能。评论将有助于澄清事情。以上是关于如果直接在 Redux reducer 中修改状态会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
在 Redux Reducer 中读取 Store 的初始状态