Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should the response logic happen, in the saga or the reducer?

Let's say I have a saga that looks so:

export function* incrementAsync(action) {
  try {
    const res = yield call(Api.signin.create, action.payload);
    yield put({ 
      type: USER_SIGN_IN_FETCH_SUCCESS,
      payload: res.data.auth
    };
  } catch (e) {
    yield put({ type: USER_SIGN_IN_FETCH_ERROR_NETWORK });
  }
}

The fech was a success, but that doesn't mean that the user was actually logged in:

res.data.auth.error could be true

My question is whether I should do things like:

if (//user was succesfully logged in)
    yield put(//user was successfully logged in)
else if //wrong username
    yield put(//wrong username)
else if //wrong password
    yield put(//wrong password)

Or should I have only one for success and one for error, and in the reducer analyze the logic and build the store relative to the response data?

like image 449
Trufa Avatar asked Mar 08 '19 20:03

Trufa


People also ask

Should I put logic action or reducer?

As of 2020, we specifically recommend putting as much logic as possible in reducers: Wherever possible, try to put as much of the logic for calculating a new state into the appropriate reducer, rather than in the code that prepares and dispatches the action (like a click handler).

Where do I put logic in Redux?

1. Logic inside the Component. You also import the action into this component file and map the action to props as well.

Can we write logic in reducer?

So, the more logic you can put in a reducer, the more logic you have that is easily testable. This is a silly one, but is often prone to mistakes. We know that as reducers are pure functions, we should not mutate the state directly inside them, instead create and return a new state object.

What is reducer in Redux saga?

At its core, Redux is only a state container that supports synchronous data flows: every time an action is sent to the store, a reducer is called and the state is updated immediately. But in an asynchronous flow, you have to wait for the response first; then, if there's no error, you can update the state.


1 Answers

Error logic should always be handled at sagas. In this particular case your API is not throwing a correct error because if your API call was not a success (200, for example), that logic should be handled at your catch statement.

Why is this error not being handled there? If you are using axios, this could happen as a consequence of a bad design of the API (i.e. returning 200 instead of 400 for an error in signin in). If it's just you doing it by hand you should throw an error and handle that logic at catch in sagas.

So my recommendation is:

  • Throw an error to the sagas to handle error logic at catch statement.
  • If you have to parse the response in order to programmatically throw the error do it at the API layer if you can.

  • Make a specific action to handle the signup error OR just make a generic FAIL action and pass an error message to it(an then store it at redux to show it).

It should look something like:

export function* incrementAsync(action) {
  try {
    const res = yield call(Api.signin.create, action.payload);
    yield put({ 
      type: USER_SIGN_IN_FETCH_SUCCESS,
      payload: res.data.auth
    };
  } catch (error) {
    yield put({ type: USER_SIGN_IN_FAIL, payload: error.message });
  }
}
like image 89
victor.ja Avatar answered Nov 14 '22 12:11

victor.ja