如何设置整个 NGRX 存储然后触发所有减速器?

How can I set an entire NGRX store and then trigger all reducers?

我能怎样?

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

背景:

我有一个 angular 应用程序,其中有许多组件与 NGRX 存储紧密耦合。

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

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

我想获取整个存储数据,然后将其重新插入到其他用户代理存储中,然后触发所有减速器以确保组件更新。

我已经知道如何获取所有商店数据。我需要一些帮助才能将它放回商店。我最需要的是如何在不编写数百个dispatch语句的情况下触发所有reducer。

Keeping browser tabs in sync using localStorage, NgRx, and RxJS可以帮到你。

既然你已经解决了第一个问题:

  1. A 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. 获取整个 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 存储:(我的顶级减速器界面如下所示)

    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 中的设置会触发所有操作