electrode-io / electrode

Web applications with node.js and React
Other
2.1k stars 299 forks source link

Integration with redux-saga #632

Closed trungpham closed 4 years ago

trungpham commented 6 years ago

Is it possible to integrate saga and have it work with SSR?

mcrowder65 commented 6 years ago

what About ssr? When the rendered content comes to the client are you saying the api calls should have already happened?

romanlv commented 5 years ago

yes it is possible and it works just fine

you should run your sagas on the server side and pass populated store to rendering logic

export function takeOnce(actionType, saga) {
  return function* _takeOnce() {
    const action = yield take(actionType);
    yield call(saga, action);
  };
}

// different root saga for ssr
// since you only need to process few actions and it should end instead of running in infinite loop
export function* ssrSaga() {
  yield all([
    // `race` can be used to handle alternatives
    fork(takeOnce(LOAD_THING.REQUEST, loadThing))
  ]);
}

export function configureStore() {
    /// create store with saga middleware 
    const store = createStore(....)

    store.runSaga = sagaMiddleware.run; 
    return store;
}

// in index-view
async function createReduxStore(req, match) {
  // extract param from react-router match object 
  const thingId = match.renderProps.params.id;

  const initialState = {

  };
  const store = configureStore(initialState);
  const sagaTask = store.runSaga(ssrSaga);
  store.dispatch({ type: LOAD_THING.REQUEST, thingId });

  // wait for saga to finish running
  await sagaTask.done;
  return store;
}

module.exports = req => {
  if (!routesEngine) {
    routesEngine = new ReduxRouterEngine({ routes, createReduxStore });
  }

  return routesEngine.render(req);
};

this is just an example, there are several way how you can structure you sagas logic...