There are times when you might be tempted to display a loading indicator to inform the user that something is happening in the background.
Reasonable times to do this are after user-initiated actions that trigger network activity - such as “Purchase a skirt”, or in the scenario where you have code-splitting enabled with react-router - “Navigate to new page”.
// ...
render() {
const {isBusy} = this.props;
if (isBusy) {
return <div>Loading...</div>;
}
return <div>Ready!</div>;
}
However what you will notice is that if the background task finishes too
quickly - depending on a powerful machine or fast network - you end up with
the DOM flickering Loading...
momentarily before settling on Ready!
.
This, of course, isn’t a great user experience so let’s try and improve that.
What I’m going to demonstrate here is the use of a timer in a custom component
that only displays the Loading...
message after a set amount of time has
passed.
import React from 'react';
class LoadingMessage extends React.Component {
constructor(props) {
super(props);
this.enableMessage = this.enableMessage.bind(this);
this.state = {
displayMessage: false,
};
this.timer = setTimeout(this.enableMessage, 250);
}
componentWillUnmount() {
clearTimeout(this.timer);
}
enableMessage() {
this.setState({displayMessage: true});
}
render() {
const {displayMessage} = this.state;
if (!displayMessage) {
return null;
}
return <div>Loading...</div>;
}
}
export default LoadingMessage;
The LoadingMessage
component here only displays the Loading...
message
after 250ms have passed. This results in a much smoother UX yet still accounts
for the case of long-running tasks.
Our render
function will now look something like:
import LoadingMessage from './LoadingMessage';
// ...
render() {
const {isBusy} = this.props;
if (isBusy) {
return <LoadingMessage/>;
}
return <div>Ready!</div>;
}