Redux - Centralize Data Fetching and Error actions
Or how to be the next hero of the day at work!
Ah, I know, you faced it. You slammed against that wall and it was terribly hard!Your reducers have grown without control and what you see…

No, that’s not me…but it could be YOU!
Ah, I know, you faced it. You slammed against that wall and it was terribly hard!Your reducers have grown without control and what you see when you open a reducer file is a huge switch statement…the never ending switch statement. We’ve all been there..
You are using React for Frontend, Redux for state management and it’s likely for you to have run into this piece of code in your actions:
And this in your reducer:
Given that your app is complex enough, these few lines will grow exponentially and maintaining such a big chunk of code is painful.
So how to solve this with a nice pattern (other buzz word)?Let’s find a solution.
From redux docs, under the very intelligently named section “Reducing Boilerplate” we read:
Redux reduces the boilerplate of Flux stores considerably by describing the update logic as a function. A function is simpler than an object, and much simpler than a class.
The
switchstatement (globally accepted as THE way to write a reducer) is not the real boilerplate. The real boilerplate of Flux is conceptual: the need to emit an update, the need to register the Store with a Dispatcher, the need for the Store to be an object (and the complications that arise when you want a universal app).
Uh!Wait you mean a reducer is a function?Sure it’s JUST a function that returns a new state, WE use a switch statement to make this routing mechanism more obvious, but we can do whatever we want in a function!
So why not writing a function that works like a catch all for specific actions, and return these in a specific key in Redux. Shall we?
Let’s take a step back to set our goal. The aim is to reduce boilerplate when writing a reducer, but not all reducers. In particular we want to avoid writing switch statements for REQUEST actions (ex. FETCH_TODOS_REQUEST) and FAILURE actions (ex. FETCH_TODOS_FAILURE). SUCCESS actions are ok to be handled manually, since we sometimes want to do more than just storing the result in our store.
Basically we’re going to write “catch all” reducers for REQUEST and FAILURE actions. We’ll see later how to handle them in our components.
So, ready….steady….go..ops, wait there is a disclaimer!This pattern will only work if your fetching actions have the _REQUEST appendix at the end. So before starting, change your actions types (typically you have these all in a file like “reducerActionTypes.js“ in a folder called “constants”, if you don’t I recommend taking some time to refactor your reducers using this pattern too).
Now let’s start:
- Create a reducer called
LoadingReducer.js(or whatever you want to call something that fetches). - Save the below code in it:
- Add the reducer to the store in a key called “fetching” or whatever key you prefer, as you normally do for every other reducer.
This guy will capture all fetching requests and store their boolean values under separate properties of the fetching key. While fetching, the property will be true and when SUCCESS or FAILURE is triggered the value will be false.
Don’t worry if you’re not following, everything will come into place, specially once you’ll try it yourself.
Let’s do a similar thing for the FAILURE actions.
- Create a file called
ErrorsReducer.jsin your reducer’s folder. - Save the below code in it:
View code on GitHub Gist
Sorry, indentation went completely wrong here…
- Add the reducer to the store in a key called “errors” or whatever key you prefer.
What this guy is doing is to save all FAILURE actions as an object under separate properties of the errors key in our store. To scale it a bit I also include a uuid for each error, you never know when an id comes useful.
Ok, now we have reduced ( a reducer, lol) switch statements for any REQUEST and FAILURE action. Now you might argue that having these values all in the same place is wrong. You’re right, it CAN be wrong. Unless you use selectors.
In fact this pattern comes with two important ingredients, the former being the reducers we’ve just created and the latter is made of two very important selectors.
PS. BTW if you’ve never heard of selectors it’s time to dive in and try learning these highly underestimated helpers. From the docs (written in a tiny paragraph under tons of other stuff):
We highly encourage the use of “selector” functions to help encapsulate the process of extracting values from specific locations in the state tree. Memoized selector functions also play a key role in improving application performance (see the following sections in this page and the Advanced Usage: Performance page for more details on why and how to use selectors.)
So a selector is nothing else than a function (tadaaaa) normally used in mapStateToProps (or a useSelector hook) to grab a piece of derived state from Redux (you actually pass state as an argument and optionally you can pass ownProps to them too), do some magic on it (if you need to, you’re not forced to as selectors can simply return a value from Redux as is) and feed them in a component as a prop.
Steps:
- Create a file called
LoadingSelector.jsin a folder close to the reducer. - Save the below code in it:
- Optionally, create an enum-like object in your constants file:
export const loadingTypes = Object.freeze({
…reducerActionTypes,
});