如何设置整个NGRX存储,然后触发所有的reducer?

时间:2019-05-29 09:24:31

标签: angular typescript ngrx ngrx-store

我怎么办?

  1. 获取整个NGRX存储数据
  2. 设置整个NGRX存储数据
  3. 触发所有减速器

背景:

我有一个角度应用程序,它的许多组件都紧密地耦合到NGRX存储。

我已将这些组件重新用于应用程序中某些信息的平面打印布局。我使用无头镀铬将应用程序打印为pdf。由于无头Chrome是与打印用户的浏览器不同的用户代理,因此没有数据。

最初,我通过在NGRX商店中发布一些商品,并在商店中替换了无头的chrome来解决了这个问题。但是,随着打印视图的扩展,商店所需的数据量已变得难以管理。

我想获取整个商店数据,然后将其重新插入另一个用户代理商店,然后触发所有reducer以确保组件更新。

我已经知道如何获取所有商店数据。我可以使用一些帮助将其放回商店。我最需要的是如何在不编写数百个调度语句的情况下触发所有reducer。

2 个答案:

答案 0 :(得分:2)

Keeping browser tabs in sync using localStorage, NgRx, and RxJS可以在这里为您提供帮助。

因为您已经解决了第一个问题:

  1. 在这里最适合使用meta-reducer:
// set state based on local storage
export function persistStateReducer(_reducer: ActionReducer<State>) {
  const localStorageKey = '__groceries';
  return (state: State | undefined, action: Action) => {
    if (state === undefined) {
      const persisted = localStorage.getItem(localStorageKey);
      return persisted ? JSON.parse(persisted) : _reducer(state, action);
    }

    const nextState = _reducer(state, action);
    localStorage.setItem(localStorageKey, JSON.stringify(nextState));
    return nextState;
  };
}

// reset the whole state via the action's payload
export function updateStateReducer(_reducer: ActionReducer<State>) {
  return (state: State | undefined, action: Action) => {
    if (action.type === 'UPDATE_GROCERIES_STATE') {
      return (<any>action).payload.newState;
    }

    return _reducer(state, action);
  };
}
  1. 当您调度动作时,所有的reducer都会被触发

答案 1 :(得分:0)

类似的事情可以做到:

  1. 获取整个NGRX存储区:

    let storeData$ = store.select(rootReducers.getRootState);
    let subscription = storeData$.subscribe(everything => {
        let json = JSON.stringify(everything);
        //do what you want with all of your data here
    });
    
  2. 设置整个NGRX存储:(我的顶级reducer界面看起来像这样)

    export interface State { 
        something: topLevelReducers1.State;
        anything: topLevelReducers2.State;
        moreThings: topLevelReducers3.State;
    }
    

    这使得有必要设置以下每个顶级字段:

    // here is the method //
    export const dispatchSetRootState = (store:Store<State>, payload: State): void => {
        store.dispatch(new SetSomethingState(payload.something));
        store.dispatch(new SetAnythingAction(payload.anything));
        store.dispatch(new SetMoreThingsAction(payload.moreThings));
    };
    
    // here is the usage //
    let everything = JSON.parse(json);
    dispatchSetRootState(store, data);
    
    // since I have a lot of combineReducers I add a short-circuit//
    export function reducers(state: any, action: any): any {
        if(action.type == SomethingActionTypes.SET_SOMETHING_PROFILE) { // Sets entire object
            return Object.assign({}, state, (<PayloadAction>action).payload);
        }
        else return combinedReducers(state, action);
    }
    
  3. 不必要,因为在#2中进行设置会触发所有操作