Achieve skeleton loading with React

June 22, 2017 0 Comments

Achieve skeleton loading with React

 

 

From Facebook and Slack to LinkedIn, skeleton loading seemed to be widely spread and is today a common practice to improve the user experience of your web application.

Technically, from what I have seen, there is two approaches to achieve this:

  • Display a fake elements which look approximately similar to the layout of your application
  • Display the exact layout of your application and replace the content by placeholders while the application is loading

If you are building your application with React there is actually an elegant solution and I will tell you the secret…

Well… it is quite trivial… while you are loading your data from your REST API, why not injecting some fake data into your application to render your components and hide the content with CSS (or inline style)?

As you might be aware of… or maybe not, I am working for Trainline and user experience is the main of our concerns as we help to prevent millions of users from being frustrated when they have to buy train tickets. At Trainline, I have the chance to work with some very good UI developers always thinking user experience first when they write code. That’s why Jamie Copeland and I had to think about a solution to have a first rendering of the layout of our pages before we get the data so that our users can have a first overview of the layout very fast.

Not this one actually but this one:

On Github: https://github.com/trainline/react-skeletor

On npm: https://www.npmjs.com/package/@trainline/react-skeletor

So let me explain in details how we managed to make it happening with React-skeletor. This article require some basics about React and High Order Functions:

Simple layout with two blog post

Assuming this is the layout of our blog and the two white area are two of our blog post. The red and green boxes are the two elements that gonna help us achieve our goal.

The first red box on the above schema is our “createSkeletonProvider”, it is a factory that return a high order function and has the following signature (pseudo-code):

const createSkeletonProvider<T> = (
dummyData: T | (props: T) => T,
predicate: (props: T) => boolean
styling?: React.CSSProperties | string
) => (WrappedComponent: React.Component): React.ComponentClass

Let’s have a look at the arguments of the factory function:

  • dummyData: The fake data you will inject in your application, it is either an object injected as props to your nested component or a function that must return the fake data
  • predicate: Function that define the loading state of your application (This will define later if we should display the fake data with the placeholder design or the real content)
  • styling: A global style that is passed down to our switch components (green boxes).

So as you can guess this component has two main functions:

  • inject the fake data
  • define the loading state of our app

The styling property is optional as we can style each switch components (green boxes) separately if we want.

Here is how we are using the skeleton provider:

export default createSkeletonProvider(
{ posts: [ ... ]},
({ posts }) => posts === undefined
)(PostsLayout);

Let’s have a look back to our schema:

Simple layout with two blog post

Now I will explain what is the green element, it’s name is “createSkeletonElement”, let’s first look at it’s signature:

const createSkeletonElement =(
type: React.Component | string,
pendingStyle?: React.CSSProperties | string
) => JSX.Element

This factory function is meant to return a React component and take two arguments:

  • first: the type of the react component, could be a string (“div”, “span”…) or a constructor of React Component
  • second: pendingStyle is the style to apply to the wrapper element to your component when your application is loading which mean: As long as the predicate of your provider (red box) return true (data in pending state).

Then we would use the “createSkeletonElement” this way:

import { createSkeletonElement } from 'react-skeletor';
const Div = createSkeletonElement('div', {
color: 'grey',
backgroundColor: 'grey'
});
<Div>
Some content not displayed while the app is loading the data
</Div>

That’s it, the component will automatically do the switch between the content or the placeholder design depending on the loading state of your application… Amazing!

  • Loading state of the app is abstracted for you as well as the switch between fake design and real content display
  • Better user experience as you visually announce where the content will be displayed so that the user will focus on the content much quicker
  • Having a first rendering of your component might improve the performance of your application when you get the data. Instead of mounting your components, they will just go through the React reconciler and only perform an update
  • Written in Typescript (type definition files for free)

This is just a minor release for now so please if you find any issue or if you would like to discuss about the API, post an issue on our Github repository. If you still struggle to understand how to implement it, have a look at our examples.

Peace, love, enjoy! ✌️🏼


Tag cloud