简体   繁体   中英

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. But what if we want to react on nested properties of the state, for example 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.

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. 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. Let us call it the stateGetter and write it to accept any number of arguments (ie depth of querying).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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