对 Angular 和 NgRx 中的嵌套状态变化作出反应
React to nested state change in Angular and NgRx
请考虑以下示例
// Example state
let exampleState = {
counter: 0;
modules: {
authentication: Object,
geotools: Object
};
};
class MyAppComponent {
counter: Observable<number>;
constructor(private store: Store<AppState>){
this.counter = store.select('counter');
}
}
在 MyAppComponent
中,我们对状态 counter
属性 发生的变化做出反应。但是,如果我们想 对状态的嵌套属性 做出反应,例如 modules.geotools
怎么办?似乎应该有调用 store.select('modules.geotools')
的可能性,因为将所有内容都放在全局状态的第一级似乎对整体状态结构不利。
更新
@cartant 的回答肯定是正确的,但是 Angular 5 中使用的 NgRx 版本需要稍微不同的状态查询方式。这个想法是,我们不能只提供store.select()
调用的键,我们需要提供一个函数,即returns具体的状态分支。让我们称它为 stateGetter 并将其编写为接受任意数量的参数(即查询深度)。
// The stateGetter implementation
const getUnderlyingProperty = (currentStateLevel, properties: Array<any>) => {
if (properties.length === 0) {
throw 'Unable to get the underlying property';
} else if (properties.length === 1) {
const key = properties.shift();
return currentStateLevel[key];
} else {
const key = properties.shift();
return getUnderlyingProperty(currentStateLevel[key], properties);
}
}
export const stateGetter = (...args) => {
return (state: AppState) => {
let argsCopy = args.slice();
return getUnderlyingProperty(state['state'], argsCopy);
};
};
// Using the stateGetter
...
store.select(storeGetter('root', 'bigbranch', 'mediumbranch', 'smallbranch', 'leaf')).subscribe(data => {});
...
select
将嵌套键作为单独的字符串,因此您的 select
调用应该是:
store.select('modules', 'geotools')
请考虑以下示例
// Example state
let exampleState = {
counter: 0;
modules: {
authentication: Object,
geotools: Object
};
};
class MyAppComponent {
counter: Observable<number>;
constructor(private store: Store<AppState>){
this.counter = store.select('counter');
}
}
在 MyAppComponent
中,我们对状态 counter
属性 发生的变化做出反应。但是,如果我们想 对状态的嵌套属性 做出反应,例如 modules.geotools
怎么办?似乎应该有调用 store.select('modules.geotools')
的可能性,因为将所有内容都放在全局状态的第一级似乎对整体状态结构不利。
更新
@cartant 的回答肯定是正确的,但是 Angular 5 中使用的 NgRx 版本需要稍微不同的状态查询方式。这个想法是,我们不能只提供store.select()
调用的键,我们需要提供一个函数,即returns具体的状态分支。让我们称它为 stateGetter 并将其编写为接受任意数量的参数(即查询深度)。
// The stateGetter implementation
const getUnderlyingProperty = (currentStateLevel, properties: Array<any>) => {
if (properties.length === 0) {
throw 'Unable to get the underlying property';
} else if (properties.length === 1) {
const key = properties.shift();
return currentStateLevel[key];
} else {
const key = properties.shift();
return getUnderlyingProperty(currentStateLevel[key], properties);
}
}
export const stateGetter = (...args) => {
return (state: AppState) => {
let argsCopy = args.slice();
return getUnderlyingProperty(state['state'], argsCopy);
};
};
// Using the stateGetter
...
store.select(storeGetter('root', 'bigbranch', 'mediumbranch', 'smallbranch', 'leaf')).subscribe(data => {});
...
select
将嵌套键作为单独的字符串,因此您的 select
调用应该是:
store.select('modules', 'geotools')