简体   繁体   中英

Why return default case instead of throw in Redux's reducer?

I have read a lot of Redux tutorials, all of the tutorial return default case instead of throw, they write something like this:

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
};

Why not throw an error since we already know the developer must've been dispatched unexisting action type? like this:

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      throw new Error(`Unknow action type: ${action.type}`)
  }
};

Why not throw?

In case of Redux, you might have multiple reducers which you combine using combineReducers to form a single store. When you dispatch an action, it is dispatched to all the reducers and only to the intended one. Hence you would have a default case where you return the current state.

And while the action is being dispatched to all the reducers, only the one that has to process the action listens to it and updates the state. This may lead to an action being dispatched but not process by any reducer but would certainly not cause an issue and will never happen unless you forgot to write this code.

However if you use a single reducer without combining them which is often a case with useReducer hook, you can throw an error if no matching action is being dispatched.

When creating reducers, the objective is not to get back an error in lieu of our new state, the objective is to return the existing state if no new state is available.

const hiringProcess = (oldListOfCandidates, action) => {
  if (action.type === 'CREATE_CANDIDATE') {
    // we care about this action
    return [...oldListOfCandidates, action.payload];
  }
   // we don't care about this action
}

So with ES2015 syntax, I have taken an array of oldListOfCandidates and add them to a brand new array and then add in a new record of action.payload .

Anyway, your question is not about key interpolation syntax but why return state; instead of throwing an error.

We don't care about getting back an error, for the purposes of reducers and what the overall redux architecture is supposed to be doing for us, what we want to return is the existing data or state if we have no new data, that's the whole point of these reducers.

const hiringProcess = (oldListOfCandidates, action) => {
  if (action.type === 'CREATE_CANDIDATE') {
    // we care about this action
    return [...oldListOfCandidates, action.payload];
  }
   // we don't care about this action
   return oldListOfCandidates;
}

So if there is no new candidate to add to state then we don't need or want an error that explains why did not update state we just want to return state; that we already have.

And as you already know the first time the reducer gets called, it will receive the value of undefined and we need to default the value of the first argument for state only like so:

const hiringProcess = (oldListOfCandidates = [], action) => {
  if (action.type === 'CREATE_CANDIDATE') {
    // we care about this action
    return [...oldListOfCandidates, action.payload];
  }
   // we don't care about this action
   return oldListOfCandidates;
}

I say for state only because I have done work at shops where they had defaulted the value of the action object and could not explain to me why they did this and at the same time did not bother to correct it, so don't do that its not necessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM