简体   繁体   English

对Angular和NgRx中的嵌套状态更改做出反应

[英]React to nested state change in Angular and NgRx

Please consider the example below 请考虑以下示例

// 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');
  }
}

Here in the MyAppComponent we react on changes that occur to the counter property of the state. MyAppComponent我们对状态的counter属性发生的更改做出反应。 But what if we want to react on nested properties of the state, for example modules.geotools ? 但是如果我们想对状态的嵌套属性做出反应 ,例如modules.geotools呢? Seems like there should be a possibility to call a store.select('modules.geotools') , as putting everything on the first level of the global state seems not to be good for overall state structure. 似乎应该有可能调用store.select('modules.geotools') ,因为将所有内容放在全局状态的第一级似乎不利于整体状态结构。

Update 更新

The answer by @cartant is surely correct, but the NgRx version that is used in the Angular 5 requires a little bit different way of state querying. @cartant的答案肯定是正确的,但Angular 5中使用的NgRx版本需要一些不同的状态查询方式。 The idea is that we can not just provide the key to the store.select() call, we need to provide a function that returns the specific state branch. 我们的想法是,我们不能只提供store.select()调用的密钥,我们需要提供一个返回特定状态分支的函数 Let us call it the stateGetter and write it to accept any number of arguments (ie depth of querying). 让我们将其称为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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM