Make sure saga is injected before actions are dispatched

867 views Asked by At

I'm having some bad time with saga injection in my app, sometimes saga is loaded before the action is dispatched and everything works, sometimes the action is fired and no saga effect is triggered. I'm using pretty standard code, here's my route:

getComponent(nextState, cb) {
    const importModules = Promise.all([
        import ('containers/HostArea/reducer'),
        import ('containers/HostArea/ActivityRegistration/reducer'),
        import ('containers/HostArea/AccommodationRegistration/reducer'),
        import ('containers/HostArea/sagas'),
        import ('containers/HostArea/'),
    ]);

    const renderRoute = loadModule(cb);

    importModules.then(([hostAreaReducer, registerActivityReducer, registerAccommodationReducer, sagas, component]) => {
        injectReducer('hostArea', hostAreaReducer.default);
        injectReducer('registerActivity', registerActivityReducer.default);
        injectReducer('registerAccommodation', registerAccommodationReducer.default);
        injectSagas(sagas.default);
        renderRoute(component);
    });

    importModules.catch(errorLoading);
},

here's my saga (I removed getCurrentHost and getHostRegistrations but of course they are defined in the same file):

export function* currentHostWatcher() {
  yield takeLatest(GET_CURRENT_HOST, getCurrentHost);
}

export function* getHostRegistrationsWatcher() {
  console.log('getHostRegistrationsWatcher');
  yield takeLatest(GET_HOST_REGISTRATIONS, getHostRegistrations);
}

export default [
  currentHostWatcher,
  getHostRegistrationsWatcher,
];

and here's the relevant part of my component:

componentDidMount() {
    console.log('componentDidMount');
    this.props.dispatch(getCurrentHost({ resolve: ((host) => this.hostAuthenticated(host)), reject: () => this.unauthenticated() }));
  }

hostAuthenticated(host) {
    console.log('host is authenticated, get his registrations');
    this.props.dispatch(getHostRegistrations({
      host,
      resolve: this.onRegistrationsLoaded,
      reject: ((err) => console.log(err)),
    }));
}

Basically what I do is dispatching an action on componentDidMount, and on success dispatching a second action, both defined in the same saga. What I see is that with the same code, just refreshing the page, sometimes the console log shows

componentWillMount
componentDidMount
getCurrentHost
getCurrentHostSuccess
getHostRegistrations

but no effect is invoked on getHostRegistrations. Other times, it all works and I see in the log:

getHostRegistrationsWatcher
componentWillMount
componentDidMount
getCurrentHost
getCurrentHostSuccess
getHostRegistrations
host registrations loaded

As you can see, in this second case the watcher is executed before the components mount and the flow is correct. So my question is: is there a way to make sure that saga is injected before component is mounted? Or any other workaround?

If you want to see the code in action, just signup here https://www.amavido.it/join (use random email/name and not facebook); once logged in, refresh and you will see some times the rendere component, some times a loading indicator which hangs forever)

0

There are 0 answers