davidmarne / built_redux_rx

epic middleware for built_redux
MIT License
6 stars 4 forks source link

Bug: reducer called 2 times when there's a stream associated with it. #4

Open zgusth opened 6 years ago

zgusth commented 6 years ago

I have a simple reducer that just sets isLoading to true when loadCounter is called and another that set it to false when loadCounterSuccess is called.

void _loadCounter(FrontendState state, Action<LocalStorage> action, FrontendStateBuilder builder) {
  builder.isLoading = true;
}

void _loadCounterSuccess(FrontendState state, Action<Null> action, FrontendStateBuilder builder) {
  builder.isLoading = false;
}

Then I have a stream that listens to the same action as the _loadCounter reducer. It just reads counter from localStorage and call _loadCounterSuccess reducer when it completes.

Observable _loadCounter(Observable<Action<LocalStorage>> stream, MiddlewareApi<AppState, AppStateBuilder, AppActions> api) {
  return stream.flatMap<void>((localStorage) {
    return Observable
        .fromFuture(localStorage.payload.read('counter'))
        .map<int>(
            (value) => value == null ? CounterState().value : int.parse(value))
        .map<void>((value) {
      api.actions.frontend.loadCounterSuccess();
      api.actions.counter.setCounter(value);
    }).handleError(() => api.actions.frontend.loadCounterFailure());
  });
}

The isLoading state should start at false, then go to true when _loadCounter is called, then go to false again when _loadCounterSuccess is called. That's working perfectly. But the stream is calling _loadCounter reducer again when it finishes, setting isLoading to true again and exploding my app 😢

Not sure if this implementation is following this from javascript.

But if it is, then that's what they say:

REMEMBER: Epics run alongside the normal Redux dispatch channel, after the reducers have already received them. When you map an action to another one, you are not preventing the original action from reaching the reducers; that action has already been through them!