我很难理解为什么第一个样本似乎工作正常,但第二个样本无法解雇观察者。
// Working reducer
return Object.assign({}, state, {
expanded: Object.assign({}, state.expanded, { clients: !state.expanded.clients })
});
// Faulty reducer - Devtools indicates a change but the observables
// seem to not respond and pass on the information down the line
newState = Object.assign({}, state);
newState.expanded.clients = !state.expanded.clients;
// Selectors
import {createSelector} from 'reselect';
export const SIDEBAR = (state: AppState) => state.sidebar;
export const SIDEBAR_UI = createSelector<AppState, SidebarUIState, SidebarState>(
SIDEBAR,
(state: SidebarState) => state.ui
);
// Sidebar service
public getSidebarUIExpandedObservable(): Observable<SidebarUIExpandedState> {
debug('Get sidebar UI expanded observable');
return this._store.select(SIDEBAR_UI_EXPANDED);
}
答案 0 :(得分:1)
Reducers需要使用不可变对象的纯函数。 因此,您不能改变newState对象,但是您必须创建一个在创建时具有明确新状态的新对象。
您的第一个示例符合不变性原则,因为在将此对象分配给目标对象(第一个参数)之前,Object.assign将第三个参数中对象的匹配属性复制到第二个参数中的对象副本。因此,原始状态保持不受影响,并且在目标对象中获得新状态。 换句话说,object.assign在内存中没有更改原始对象状态,并且返回值提供了准备好(不需要进一步的突变)新状态对象。 有关Object.assign()的更多信息:https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
在第二种情况下,首先创建一个新对象(不变性仍然有效),随后,通过赋值布尔值来改变状态,因此不变性原则被破坏,而且reducers通常不接受这个。
答案 1 :(得分:1)
在reducer中使用以下内容:
newState = Object.assign({}, state);
newState.expanded.clients = !state.expanded.clients;
state.expanded
的内容正在变异。
即newState.expanded
和state.expanded
引用相同的对象,并且该对象的client
属性正在变异。查看expanded
的代码将看到对象引用未更改,并且将假定内容未更改,但您已通过切换其clients
属性的值来对其进行了更改。
答案 2 :(得分:1)
而不是:
newState = Object.assign({}, state);
newState.expanded.clients = !state.expanded.clients;
做
return Object.assign(
{},
state,
{
expanded: Object.assign(
{},
state.expanded,
{
clients: !state.expanded.clients
}
)
}
);
特技: 当你有Typescript&gt; = 2.1.4时,你就可以这样做
return {
...state,
{
expanded: {
...state.expanded,
{
clients: !state.expanded.clients
}
}
}
};