Asynchronous Operations in React-Redux
January 29th, 2019 | By Camilo Reyes | 5 min read
A quick tutorial about Asynchronous Operations in React-Redux: Learn how to use Redux-Thunk to do much of this work.
Asynchronous operations are a difficult challenge while programming the browser.
It is hard to conceptualize sending a request and waiting for a response without blocking. Browsers can put this behind a callback and continue code execution.
The React-Redux libraries do much of the work for you without compromising simplicity. Think of React as the library that renders UI components in plain HTML. Redux is a state management library with asynchronous capabilities.
In the old days, you could delegate asynchronous behavior through chained callbacks. This had limitations because a large callback chain ran the risk of callback hell. A strong sense of discipline was necessary to keep the code clean. Callback hell could turn any project into mush when you lack SOLID principles.
With React-Redux, what sort of improvements are available in async programming? For this, we’ll do a demo with planets in the solar system.
The goal is to load them on a page asynchronously with images. We’ll focus on Redux’s state management and how it handles asynchronous behavior.
We’ll assume you have a working knowledge of NPM and ES6. To keep the code samples focused, we’re only showcasing relevant code. If you’re interested in more of the plumbing, feel free to check out the entire demo on GitHub.
The dependencies for this demo will be as follows: If you’re following along, type:
npm install --save next react react-dom prop-types axios redux react-redux redux-thunk redux-logger
Make sure there is a package.JSON is available to save all dependencies. Feel free to explore what each dependency will do. The two to remember are Axios to make async requests and redux-thunk to manage async state.
To start, capture the constants we will use throughout the demo. These constants will drive the state of async operations:
export const REQUEST_PLANETS = 'request planets';
export const RECEIVE_PLANETS = 'receive planets';
The request gets triggered by the component’s componentDidMount method, which fires fetchPlanets. To help you visualize the result, here is the working demo:
Why Not Use Ajax?
You can think of Redux-Thunk as another way to do Ajax in the browser.
A thunk describes a function that replaces a computation you then calculate later. Execution does not happen immediately but gets delegated. For example:
const foo = (i) => i + 1;
In JavaScript, you may think of a thunk as a callback function.
A callback function delegates computation so it can execute later. In Redux-Thunk, you still make use of this same callback concept, but in an abstract way. Redux’s statement management system handles all the implementation details. This eliminates the risk of long callback chains and callback hell.
Time to wire up Redux-Thunk in the Redux-Store:
const logger = createLogger();
const planetStore = createStore(
reducers,
applyMiddleware(logger, thunk)
);
With this, you’re all set for some asynchronous programming. Thunk now sets up action dispatchers so it can handle a Thunk callback function.
The Redux-Store is where you set up Redux-Thunk as a middleware pipeline. Note: We take this opportunity to include the logger, so we can see Redux-Thunk in action. The logger captures dispatcher messages and prints them in the browser’s console.
Async Actions with Axios
Next, let’s set up the actions that get dispatched through the store. In Redux, actions are like messages that ripple across the state management system.
You can think of any UI interaction as an action. This fits well when you imagine firing and receiving messages to manage the state. The UI notes a state change, fires an action, and Redux handles state changes through messages.
The PlanetAction is as follows:
let PlanetAction = {
fetchPlanets() {
return (dispatch) => {
dispatch({ type: REQUEST_PLANETS });
axios.get('/static/solar-system-planets.json')
.then((response) => dispatch({
type: RECEIVE_PLANETS,
success: true,
planets: response.data.planets
}))
.catch((error) => dispatch({
type: RECEIVE_PLANETS,
error: error.message,
planets: null
}));
};
}
};
Note the use of Axios to encapsulate Ajax requests in the browser through a promise. The .then() function handles a successful response.
The .catch() function handles an error. React-Thunk makes it possible for you to use a thunk as the return type. The underlying state management system handles the dispatcher. Note the use of a thunk with return (dispatch) => { }.
To handle errors gracefully, we opted to capture the error.message in the dispatcher’s message. This helps us debug the app because this message shows up in the console. The .catch() function enables error handling through the dispatcher callback function.
This is what the messages look like in the console:
React Reducers
The reducer picks up messages and returns the current state through a pure function. A pure function is one where, given an input, you always get back the same result. This paradigm is functional programming, and it reduces unpredictable behavior in your programs.
Below is the reducer that changes state during asynchronous operations:
const INITIAL_STATE = [];
const planets = (state = INITIAL_STATE, action) => {
switch (action.type) {
case REQUEST_PLANETS:
return INITIAL_STATE;
case RECEIVE_PLANETS:
return action.planets;
default:
return state;
}
};
We can reuse INITIAL_STATE because the app has the same data at page load and during the request. Note that the result will always match a given input one-to-one.
Reducers use a pure function and return the state given by where you are in the async operation. The action dispatcher then uses this pure function to calculate the current state.
Note that this reducer is the callback function inside the thunk function. Now, below is the happy path with console messages:
Conclusion
Redux-Thunk has an asynchronous approach that wraps around a thunk function. This embraces the best of programming, such as delegates and pure functions.
If you are familiar with legacy Ajax through callbacks, then a thunk is not very different.
React-Redux grabs the best of what you know about vanilla JavaScript and wraps it for easier use. This library doesn’t reinvent the wheel but automates sound programming through abstractions.
Jscrambler
The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.
View All ArticlesMust read next
Asynchronous Operations in JavaScript
Mastering asynchronous operations in JavaScript is a key part of a Web Developer's journey. Here, we discuss callbacks, promises, async/await, and pitfalls.
September 26, 2019 | By Camilo Reyes | 4 min read
How To Use React Native AsyncStorage
Persisting data in mobile apps can be valuable to increase the user experience. In this post, we show how to implement and use this asynchronously in React Native.
April 29, 2022 | By Aman Mittal | 6 min read