为什么 Redux 中的对象应该是不可变的?
Why should objects in Redux be immutable?
为什么 Redux 中的对象应该是不可变的?
我知道某些框架(例如 Angular2)将使用 onPush 并且可以利用不变性来比较视图状态以加快渲染速度,但我想知道是否还有其他原因,因为 Redux 与框架无关,但它在自己的文档中提到要使用不变性(无论框架如何)。
感谢任何反馈。
Redux 是一个将状态表示为(不可变)对象的小型库。 新状态通过纯函数传递当前状态来创建一个全新的object/application状态。
如果你那边的 eyes-glazed 不用担心。总而言之,Redux 不会通过修改对象来表示应用程序状态的变化(就像使用 object-oriented 范例一样)。相反,状态变化表示为 输入对象和输出对象 (var output = reducer(input)
) 之间的 差异。如果你改变 input
或 output
你使状态无效。
换句话说,不变性是 Redux 的要求,因为 Redux 将您的应用程序状态表示为 "frozen object snapshots"。使用这些 离散快照 ,您可以保存状态或反转状态,并且通常有更多 "accounting" 用于所有状态更改。
您的应用程序的状态仅 由一类称为 reducer 的纯函数更改。 Reducers 有两个重要的属性:
- 它们从不变异,返回新构建的对象:这允许在没有side-effects[=68的情况下对输入+输出进行推理=]
- 他们的签名是always
function name(state, action) {}
,所以很容易组合他们:
假设状态如下所示:
var theState = {
_2ndLevel: {
count: 0
}
}
我们想增加计数,所以我们制作这些减速器
const INCR_2ND_LEVEL_COUNT = 'incr2NdLevelCount';
function _2ndlevel (state, action) {
switch (action.type) {
case INCR_2ND_LEVEL_COUNT:
var newState = Objectd.assign({}, state);
newState.count++
return newState;
}
}
function topLevel (state, action) {
switch (action.type) {
case INCR_2ND_LEVEL_COUNT:
return Object.assign(
{},
{_2ndLevel: _2ndlevel(state._2ndlevel, action)}
);
}
}
注意使用 Object.assign({}, ...)
在 each reducer 中创建一个全新的对象:
假设我们已经将 Redux 连接到这些 reducer,那么如果我们使用 Redux 的事件系统来触发状态更改...
dispatch({type: INCR_2ND_LEVEL_COUNT})
...Redux 将调用:
theNewState = topLevel(theState, action);
注意:action
来自 dispatch()
现在 theNewState
是一个 全新的对象 。
注意:您可以使用 a library (or new language features) 强制不变性,或者只是小心不要改变任何东西:D
为了更深入地了解,我强烈建议您查看 Dan Abramov(创作者)的 this video。它应该可以回答您的任何挥之不去的问题。
Redux documentation 中提到了不变性的以下好处:
- Both Redux and React-Redux employ shallow equality checking. In particular:
- Redux's combineReducers utility shallowly checks for reference changes caused by the reducers that it calls.
- React-Redux's connect method generates components that shallowly check reference changes to the root state, and the return values from the mapStateToProps function to see if the wrapped components actually need to re-render. Such shallow checking requires immutability to function correctly.
- Immutable data management ultimately makes data handling safer.
- Time-travel debugging requires that reducers be pure functions with no side effects, so that you can correctly jump between different states.
很棒的文章https://medium.cobeisfresh.com/how-redux-can-make-you-a-better-developer-30a094d5e3ec
Along with immutable data, pure functions are one of the core concepts
of functional programming
Redux 使用不变性的主要原因是它不必遍历对象树来检查每个键值的变化。相反,它只会检查对象的引用是否已更改,以便在状态更改时更新 DOM。
基于官方文档:
你不能在 Redux 中改变状态有几个原因:
- 它会导致错误,例如 UI 无法正确更新以显示最新值
- 这让人更难理解状态更新的原因和方式
- 这使得编写测试变得更加困难
- 它破坏了正确使用“time-travel调试”的能力
- 它违背了 Redux 的预期精神和使用模式
为什么 Redux 中的对象应该是不可变的? 我知道某些框架(例如 Angular2)将使用 onPush 并且可以利用不变性来比较视图状态以加快渲染速度,但我想知道是否还有其他原因,因为 Redux 与框架无关,但它在自己的文档中提到要使用不变性(无论框架如何)。
感谢任何反馈。
Redux 是一个将状态表示为(不可变)对象的小型库。 新状态通过纯函数传递当前状态来创建一个全新的object/application状态。
如果你那边的 eyes-glazed 不用担心。总而言之,Redux 不会通过修改对象来表示应用程序状态的变化(就像使用 object-oriented 范例一样)。相反,状态变化表示为 输入对象和输出对象 (var output = reducer(input)
) 之间的 差异。如果你改变 input
或 output
你使状态无效。
换句话说,不变性是 Redux 的要求,因为 Redux 将您的应用程序状态表示为 "frozen object snapshots"。使用这些 离散快照 ,您可以保存状态或反转状态,并且通常有更多 "accounting" 用于所有状态更改。
您的应用程序的状态仅 由一类称为 reducer 的纯函数更改。 Reducers 有两个重要的属性:
- 它们从不变异,返回新构建的对象:这允许在没有side-effects[=68的情况下对输入+输出进行推理=]
- 他们的签名是always
function name(state, action) {}
,所以很容易组合他们: - 他们的签名是always
假设状态如下所示:
var theState = {
_2ndLevel: {
count: 0
}
}
我们想增加计数,所以我们制作这些减速器
const INCR_2ND_LEVEL_COUNT = 'incr2NdLevelCount';
function _2ndlevel (state, action) {
switch (action.type) {
case INCR_2ND_LEVEL_COUNT:
var newState = Objectd.assign({}, state);
newState.count++
return newState;
}
}
function topLevel (state, action) {
switch (action.type) {
case INCR_2ND_LEVEL_COUNT:
return Object.assign(
{},
{_2ndLevel: _2ndlevel(state._2ndlevel, action)}
);
}
}
注意使用 Object.assign({}, ...)
在 each reducer 中创建一个全新的对象:
假设我们已经将 Redux 连接到这些 reducer,那么如果我们使用 Redux 的事件系统来触发状态更改...
dispatch({type: INCR_2ND_LEVEL_COUNT})
...Redux 将调用:
theNewState = topLevel(theState, action);
注意:action
来自 dispatch()
现在 theNewState
是一个 全新的对象 。
注意:您可以使用 a library (or new language features) 强制不变性,或者只是小心不要改变任何东西:D
为了更深入地了解,我强烈建议您查看 Dan Abramov(创作者)的 this video。它应该可以回答您的任何挥之不去的问题。
Redux documentation 中提到了不变性的以下好处:
- Both Redux and React-Redux employ shallow equality checking. In particular:
- Redux's combineReducers utility shallowly checks for reference changes caused by the reducers that it calls.
- React-Redux's connect method generates components that shallowly check reference changes to the root state, and the return values from the mapStateToProps function to see if the wrapped components actually need to re-render. Such shallow checking requires immutability to function correctly.
- Immutable data management ultimately makes data handling safer.
- Time-travel debugging requires that reducers be pure functions with no side effects, so that you can correctly jump between different states.
很棒的文章https://medium.cobeisfresh.com/how-redux-can-make-you-a-better-developer-30a094d5e3ec
Along with immutable data, pure functions are one of the core concepts of functional programming
Redux 使用不变性的主要原因是它不必遍历对象树来检查每个键值的变化。相反,它只会检查对象的引用是否已更改,以便在状态更改时更新 DOM。
基于官方文档:
你不能在 Redux 中改变状态有几个原因:
- 它会导致错误,例如 UI 无法正确更新以显示最新值
- 这让人更难理解状态更新的原因和方式
- 这使得编写测试变得更加困难
- 它破坏了正确使用“time-travel调试”的能力
- 它违背了 Redux 的预期精神和使用模式