Search code examples
reactjsreduxredux-thunkredux-saga

How to handle erros with redux saga


I try to error handling with redux saga. Far now its always returning 404 error when i changed the api url. I organized my reducer and redux saga. but ı can't reach to fetching item This is my Reducer

const homeReducer = (state : Object = initialState, action : Object) => {

  switch (action.type) {
    case HOME.GET_MOVIES_START:
      return {
        ...state,
        ProgramsLoading: true,
        fetching: true
      };

    case HOME.GET_MOVIES_FINISH:
      return {
        ...state,
        ProgramsLoading: false,
        programs: action.programs,
        fetching: true
      };
    case HOME.GET_MOVIES_REJECTED:
      return {
        ...state,
        ProgramsLoading: false,
        fetching: false
      };
    default:
      return state;
  }

};

And It's my Redux Saga. There is call api with axios. And manipulate to data in there

function* getPrograms() {
  const { data } = yield call(axios.get, "http://localhost:3000/entries");
  const fetching = false;
  const defaultValue = {
    SeriesFilteredData: [],
    MoviesFilteredData: []
  };
  const reducerFunction = (accumulator, currentValue) => {

    if (currentValue.releaseYear < 2010) {
      return accumulator;
    }
    if (currentValue.programType === "series") {
      accumulator.SeriesFilteredData.push(currentValue);
    }
    else if (currentValue.programType === "movie") {
      accumulator.MoviesFilteredData.push(currentValue);
    }
    return accumulator;
  };
  const results = data.reduce(reducerFunction, defaultValue);

  if (results) {
    yield put(homeActions.getProgramsFinish(results));
  }
  else {
    yield put(homeActions.getProgramsRejected({ ProgramsLoading: false }));
  }

}
function* homeFlow() {
  console.log(getPrograms, "getPrograms");
  yield call(delay, 2000);
  yield call(getPrograms);
}

export default function* homeSaga() {
  yield takeEvery(HOME.GET_MOVIES_START, homeFlow);
}

How Can I handle to any errors ?


Solution

  • Place all your getPrograms function in a try catch and trigger (put) the homeActions.getProgramsRejected({ ProgramsLoading: false }) action in the catch block

    function* getPrograms() {
        try {
            const { data } = yield call(axios.get, "http://localhost:3000/entries");
    
            // ... the rest of your code
    
            if (results) {
              yield put(homeActions.getProgramsFinish(results));
            }
            else {
              yield put(homeActions.getProgramsRejected({ ProgramsLoading: false }));
            }
        }
        catch(error) {
            yield put(homeActions.getProgramsRejected({ ProgramsLoading: false }));
        }
    }
    

    Then you can improve it avoiding to write two identical yield put(homeActions.getProgramsRejected({ ProgramsLoading: false })); calls. Take a look

    function* getPrograms() {
        try {
            const { data } = yield call(axios.get, "http://localhost:3000/entries");
    
            // ... the rest of your code
    
            if (results) {
              yield put(homeActions.getProgramsFinish(results));
            }
            else {
                throw new Error('No results');
            }
        }
        catch(error) {
            yield put(homeActions.getProgramsRejected({ ProgramsLoading: false }));
        }
    }
    
    • if the axios call fails the catch block puts the homeActions.getProgramsRejected action
    • if it doesn't fail but there aren't results (your initial management) it throws a new error and, again, the catch block puts the homeActions.getProgramsRejected action

    Let me know if it helps you 😉