简体   繁体   中英

Rehydrate @ngrx/store from @ngrx/db

I want to rehydrate @ngrx/store when page loads/bootstrap.

I saved previous state in browser's IndexedDB with @ngrx/db and I want to retrive this information at INIT_ACTION of my store.

To make this I see that exist the metaReducers like:

export function indexedDBSyncReducer(reducer: ActionReducer<any>): ActionReducer<any> {
    return function newReducer(state, action: any) {
        if (action.type == 'INITIAL_STATE') {
            // Read information to db and set nextState

        }
        const nextState = reducer(state, action);
        return nextState;
    };
}

The problem is that to retrive information from @ngrx/db I need to have the contructor for access. like this .

The metaReducers are pure function so, How can I inject the Database provider to use it in my reducer?

You can use managed classes with a method that return the reducer function:

@Injectable()
export class AccountReducerFactory {
  // here you get your db access (or any managed service) injected
  constructor(private dbService: DbService) {}

  createReducer() {
    return (state: AccountState, action: Action) => {
      if(action.type === 'INITIAL_STATE') {
        const initialState = this.dbService.readInitialState()
        // do something with your initial state
      }
    }
  }
}

Then you provide your reducer using an injection token (as documented here ). Here is a simplified example for an 'account' feature module:

export const ACCOUNT_REDUCER_TOKEN = new InjectionToken<ActionReducer<Map<string, Account>>>('Account state reducer')

export function getAccountReducer(accountReducerFactory: AccountReducerFactory): ActionReducer<Map<string, Account>> {
  // here you create a reducer function with access to other managed services
  return accountReducerFactory.createReducer()
}

@NgModule({
  imports: [
    StoreModule.forFeature('account', ACCOUNT_REDUCER_TOKEN)
  ],
  providers: [
    {
      provide: ACCOUNT_REDUCER_TOKEN,
      // here your AccountReducerFactory class will be instantiated with its deps
      deps: [AccountReducerFactory],
      useFactory: getAccountReducer
    }
  ]
})
export class AccountModule {
}

This answers how to access a service in an ngrx reducer. As for your original question, you will face another challenge which is harder to overcome: indexedDb is asynchronous, ngrx initialisation is not. I wrote a short blog post about that here .

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