How to modify NGRX store not in reducer?

In the code I have something like:

this.store.dispatch(new LoadGame(id));

this action is handled by one of the @Effect and fires new LoadGameSuccess(game). Than this game is passed to reducer to update GameState. However how can I change the GameState to reflect that game is currently being loaded? Making one more action and handle it in the reducer looks not very good. The application becomes 'actions-hell'... Should I do this in the @Effect ?

Upvotes: 0

Views: 136

Answers (1)

xandermonkey
xandermonkey

Reputation: 4422

Don't try to go against the design pattern. It's designed that way for a reason.

If you have an action that may or may not impact the state of the store based on some other logic, the right way to do it is have an effect that listens for the action, performs the logic, and then dispatches a new action.

That being said - there's no reason you can't handle the LoadGame action in both the store and the effect. Something like this:

Your effect

@Effect()
  loadGame$ = this.actions$.pipe(
    ofType<LoadGame>(GameActions.LoadGame),
    mergeMap(url => this.http.get<Game>("http://wherever.you.get.your.game.data.from")
        .pipe(
            game => [new LoadGameSuccess(game), new AnyOtherActionsHere()]
        )
    )
);

Your Reducer

export function reducer(state = initialState, action: GameActions): State {
  switch (action.type) {
    case GameActions.LoadGame:
      return {
        ...state,
        isGameLoading: true,
      };
    case GameActions.LoadGameSuccess:
      const { game } = action.payload
      return {
        ...state,
        game
        isGameLoading: false,
      };
    }
}

Note that there is no concern for a race condition in doing this.

Upvotes: 1

Related Questions