Search code examples
reactjsreduxredux-saga

It's a good practice call a saga like a normal function?


Today checking codebase with my team we encounter that we have a mix of dispatch an action with put or call a saga directly with the call method. I always dispatch the action with the put but dunno if call the saga directly is wrong or it's the same.

Any clarification or documentation on this?

function* anotherSaga() {
yield* put(logoutRequest({ tokenExpired: true }));
}
function* anotherSaga() {
yield* call(logoutSaga, {payload: { tokenExpired: true }});
}
export function* watchRemoteConfigSaga() {
  yield* takeEvery(logoutRequest, logoutSaga);
  yield* takeEvery(anotherSaga, anotherSaga);
}

Solution

  • Both options are fine.

    The way I like to think about it is that redux actions are essentially events. So if I just want to let the rest of the application know that something happened I will dispatch an action and the rest of the app can react to it, but for the original saga it doesn't matter either way. If its something that is part of the expected functionality of the original saga then it shouldn't be an event but a direct call using the call effect.

    Example of an action/event:

    function* fetchItemsSaga() {
      const data = yield fetch('/items')
      yield put(saveItems(data))
    }
    
    function* itemListenerSaga() {
      yield takeEvery(SAVE_ITEMS, function*(){
        console.log('New items are stored')
      }
    }
    

    Example of a direct call:

    function* fetchItemsSaga() {
      const data = yield fetch('/items')
      // in this case, the logic in saveItemsSaga is necessary functionality of fetchItemsSaga
      yield call(saveItemsSaga, data)
    }
    
    function* saveItemsSaga(data) {
      console.log('New items are stored')
      yield put(saveItems(data))
    }
    

    Notice how the contract changes in the first case the itemListenerSaga depends on fetchItemsSaga while in the second case fetchItemsSaga depends on saveItemsSaga - this will likely affect how you import stuff in your app and doing this right might be important for correct encapsulation of various layers of your app.