ReactT2 Dark_1200x303

Let’s learn why skeleton screens (wireframe previews) are a better load indicator than the usual old spinners, and then look at how to add them.

In this article, we are going to learn more about how loading content should be handled properly in modern applications and why skeleton screens can be the best alternative for it.

Communication is the key to modern applications’ success nowadays. Every company needs to show content to its users properly in order to be more successful—it makes a total difference in for users and in the future.

But showing the content properly is not only the one thing that you should be doing to improve your communication with your user and enhance their final experience.

Loading Content and UX

Loading spinners have always been the main alternative for loading screens. They are easy to use, there are a lot of different packages and icons available in the community and everyone knows exactly what it means when we see a loading spinner.

The problem is that loading spinners create the sensation it’s loading slowly. A loading spinner does not keep the user engaged. It deviates from the user’s perception about how the content is going to be displayed and sometimes creates a feeling of frustration.

Bill Chung conducted very complex and important research about skeleton screens and noticed that skeleton screens, in fact, are perceived as being shorter in duration versus a blank screen or a loading spinner.

One of the keys to success is to keep users engaged while content is loading, and that’s why skeleton screens are the best alternative to show that the content is loading in your application.

A skeleton screen is a loading placeholder that displays a non-interactive wireframe preview similar to the content that is currently loading, showing boxes where text and images will be once loading is complete.

Skeleton screens keep the user engaged and help to reduce loading-time frustration. The user creates an accurate perception about how the content is going to be displayed even before it’s loaded.

Three gray horizontal bars, reminiscent of lines of text, fade on and off, giving a sense of "loading."

Skeleton screens are everywhere in web now, being used by a lot of huge companies such as Facebook, Medium, YouTube, etc.

Now we are going to implement skeleton screens in a React application and see how it helps our users to stay more engaged and less frustrated.

Skeletons in React Apps

There are a lot of different skeleton screen packages that can be used in React. Each one of them uses a different approach, so in this article, we are going to use one of the best and most intuitive packages for skeleton screens in React.

We are going to use the react-loading-skeleton package created by David Tang. One of the main advantages of this package is that it adapts the skeleton screen to the styles of your content. Unlike other packages that are available, by using this package there’s no need for you to create a skeleton screen with the exact size that you want to use—the <Skeleton> component will automatically fill the correct sizes.

Let’s get started by creating a new application using Create React App:

npx create-react-app skeleton-react

Now we are going to install the react-loading-skeleton package:

yarn add react-loading-skeleton

We are going to create a simple application that makes a request to the Chuck Norris API. Every time we reload our application, we will make a new request and update our state data.

Let’s start by creating a component called Joke. Inside this component, we will use our skeleton screen. First, let’s import a few things that we are going to use:

import React from 'react';
import Skeleton from 'react-loading-skeleton';

The Joke component will receive three props: joke, loading and getNewJoke. The joke prop will be the joke that we will receive from the API; the loading prop is a boolean value to check if the joke is currently loading; and the getNewJoke function will be responsible for getting a new joke from the API for us.

const Joke = ({ joke, loading, getNewJoke }) => {
  return (
    ...
  )
}

Remember that react-loading-skeleton package does not require us to create a skeleton screen with the specific size of our components? All we have to do is display the Skeleton component while our content is loading.

So, we are going to create an h1 for our id, an img for our image and another h1 for our value.

<h1>{loading ? <Skeleton /> : joke.id}</h1>
{loading ? <Skeleton /> : <img src={joke.icon_url} height='60px' width='60px' />}
<h1>{loading ? <Skeleton /> : joke.value}</h1>

We will also have a button and pass our getNewJoke function as an onClick method, so every time we click it, it will bring to us a new joke.

<button onClick={getNewJoke}>Get joke</button>

This is what our Joke component will end up looking like:

import React from 'react';
import Skeleton from 'react-loading-skeleton';

const Joke = ({ joke, loading, getNewJoke }) => {
  return (
    <div>
      <h1>{loading ? <Skeleton /> : joke.id}</h1>
{loading ? <Skeleton /> : <img src={joke.icon_url} height='60px' width='60px' />}
      <h1>{loading ? <Skeleton /> : joke.value}</h1>
      <button onClick={getNewJoke}>Get joke</button>
    </div>
  )
}
export default Joke;

Now that our Joke component is ready, we are going to work on our App component. First, import our Joke component.

We need now to create our state. We will have a joke state which will be an object and a loading boolean state.

const [joke, setJoke] = useState({});
const [loading, setLoading] = useState(false);

Create a new function called getNewJoke. Inside this function we will make a new request to the Chuck Norris API and save the response to our state.

const getNewJoke = () => {
  setLoading(true);
  fetch('https://api.chucknorris.io/jokes/random')
    .then(r => r.json())
    .then(data => {
      const { icon_url, id, value } = data;
      setJoke({ icon_url, id, value });
      setLoading(false);
    });
}

Notice that we are setting our loading state to true at the beginning of the function. After we set our joke state, we set the loading state to false again.

We will use the useEffect hook to guarantee that every time our component is re-rendered we get a new joke by calling the getNewJoke function inside the hook, like this:

useEffect(() => {
  getNewJoke();
}, []);

Now all we have to do is pass our Joke component inside our App component, and our whole App component is going to look like this:

import React, { useEffect, useState } from 'react';
import Joke from "./Joke";

const App = () => {
  const [joke, setJoke] = useState({});
  const [loading, setLoading] = useState(false);

  const getNewJoke = () => {
    setLoading(true);
    fetch('https://api.chucknorris.io/jokes/random')
      .then(r => r.json())
      .then(data => {
        const { icon_url, id, value } = data;
        setJoke({ icon_url, id, value });
        setLoading(false);
      });
  }

  useEffect(() => {
    getNewJoke();
  }, []);

  return (
    <div>
      <Joke joke={joke} loading={loading} getNewJoke={getNewJoke} />
    </div>
  );
}
export default App;

We have now an application with a skeleton screen react-loading-skeleton package. All we had to do was to use the Skeleton component and the package automatically filled the correct sizes for us.

The Skeleton for an h1, an image, and another h1 is shown while a joke loads. After it loads, we see an emoji style icon of Chuck Norris and a different joke than previously loaded.

When using skeleton screen, we should be careful to not use it everywhere in our application and diminish our user experience. It does not make sense to use a skeleton screen in components where the content is not going to be changed, such as buttons or icons. We should only use it where content is actually going to be updated.

Conclusion

The usage of loading spinners nowadays is becoming outdated. It creates a sense of frustration among your users and can feel like the content is taking longer to load than it really is. Skeleton screens can be a very responsive and intuitive solution for showing a non-interactive preview similar to your content while the actual content is loading.


Leonardo Maldonado
About the Author

Leonardo Maldonado

Leonardo is a full-stack developer, working with everything React-related, and loves to write about React and GraphQL to help developers. He also created the 33 JavaScript Concepts.

Related Posts

Comments

Comments are disabled in preview mode.