Updated to react-promise-tracker v 2.0
When you are developing your web application, you have to perform asynchronous operations, e.g. perform a fetch/ajax call to obtain data from the server. Sometimes you need to do silent background operations, whereas in other cases you need to block the user interface or notify them that something is going on.
A typical way of handling this, is using a boolean flag to show/hide the spinner, something like:
onClick = () => {
/*
Begin by setting loading = true, and use the callback function
of setState() to make the ajax request. Set loading = false after
the request completes.
*/
this.setState({ loading: true }, () => {
Axios.get('/endpoint')
.then(result => this.setState({
loading: false,
data: [...result.data],
}));
});
}
render() {
const { data, loading } = this.state;
return (
<div>
<button onClick={this.onClick}>
Load Data
</button>
{/*
Check the status of the 'loading' variable. If true, then display
the loading spinner. Otherwise, display the results.
*/}
{loading ? <LoadingSpinner /> : <ResultsTable results={data} />}
</div>
);
}
What's wrong with this approach? Let's list the pitfalls:
You can try to handle all of these scenarios, but you will probably end up with race conditions, plus a mix of UI and business logic code.
What can we do? You can leverage this complexity to a microlibrary like React Promise Tracker, which will take care of all those edge cases, making it easier for you to manage it all. Features of this library:
Let's add this library to an existing project.
As a starting point, we will take a simple application that displays a list of users. We are hitting the json server api ... (we have intentionally added a delay, just to create the opportunity of showing you the loading indicator). Right now we have the following user experience:
We want to display a loading indicator whenever the user clicks on the Load button, and hide it once the corresponding ajax call has been completed. Something like this:
npm install
npm install react-promise-tracker --save
./src/index.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import { App } from './app';
+ const LoadingIndicator = props => {
+ return (
+ <h1>Hey some async call in progress ! </h1>
+ );
+ }
render(
<div>
<App />
</div>,
document.getElementById('root'));
Let's start by importing the promiseTrackerHoc
./src/index.js
import React from 'react';
+ import { usePromiseTracker } from "react-promise-tracker";
Use the react-promise-tracker usePromiseTracker hook.
./src/index
const LoadingIndicator = props => {
+ const { promiseInProgress } = usePromiseTracker();
return (
+ promiseInProgress &&
<h1>Hey some async call in progress ! </h1>
);
}
./src/index.ts
render(
<div>
<App />
+ <LoadingIndicator/>
</div>,
document.getElementById('root'));
First we will add the import to the react promise tracker library:
./app.js
import { UserTable, LoadButton } from './components';
import './app.css';
+ import { trackPromise } from 'react-promise-tracker';
Then we will wrap the fetch call with a trackPromise method:
app.js
onLoadTables() {
this.setState({
users: [],
});
+ trackPromise(
userAPI.fetchUsers()
.then((users) => {
this.setState({
users,
})
- });
+ }));
}
npm install react-loader-spinner --save
First let's add the corresponding import:
./src/index.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import { App } from './app';
+ import Loader from 'react-loader-spinner';
Now let's pimp our loading indicator:
./src/index.js
const LoadingIndicator = props => {
const { promiseInProgress } = usePromiseTracker();
return promiseInProgress &&
- <h1>Hey some async call in progress ! </h1>;
+ <div
+ style={{
+ width: "100%",
+ height: "100",
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center"
+ }}
+ >
+ <Loader type="ThreeDots" color="#2BAD60" height="100" width="100" />
+ </div>
};
-If we run the application now, we can see that we are getting a better-looking loading indicator.
npm start
Handling async loading indicators by yourself can be okay for very small applications. However, for the rest of the scenarios it's a good idea to leave the task to a microlibrary, like React Promise Tracker.
If you want to learn more about React-Promise-Tracker, you can check out its github page. It contains live examples plus documentation.
https://github.com/Lemoncode/react-promise-tracker
We are a team of Javascript experts. If you need coaching or consultancy services, don't hesitate to contact us.
C/ Pintor Martínez Cubells 5 Málaga (Spain)
info@lemoncode.net
+34 693 84 24 54
Copyright 2018 Basefactor. All Rights Reserved.