Great UX With These Loading Techniques
We will be discussing 3 types of loading a user may encounter while interacting with your application.
This discussion is mostly oriented towards single page apps but is relevant for any web app
Backend Operations
This is the most straightforward way of handling a loading state and along with loading content the most common one.
Let’s say that in front of you is a login form and you’ve just typed in your credentials. Now you may want to submit your credentials to authenticate yourself and access your private content. After clicking the submit button a few things can happen.
- The server request performs flawlessly and you get a desired response
- The request either errors or times out
Either way, a certain amount of time passes by during which we are unsure of the outcome of the operation.
First we ought to communicate to the user that the operation has started and update the user as much as possible about the progress of the operation. For their own benefit, you may also want to disallow the user to initiate any new operation of the same kind until the first one has completed.
An easy way to accomplish that objective is to disabled the submit button and/or set the buttons children and cursor to loading, until one of the beforementioned outcomes meet the users request.
Loading Content
The modern trend of handling content loading is to display a discretely shimmer shape ( usually a rectangle or a circle ), which resembles the shape of the content which shall be loaded form the server.
This is good for a number of reasons. Firstly, it sets the users expextations for what to expect after the loading has finished ( it is much more descriptive than a simple loading spinner ). Secondly, the loaded content doesn’t appear out of the blue, but instead gently emerges from the shimmering shapes.
Now the question is how to create those shimmering shapes for the content you need to load. Considering the countless shapes data can have an all of the different arrangements finding an easy way to generate loading shapes seems like a difficult task.
The obvious way to do it would be to create the loading shapes ad hoc.
Since you’re a developer you probably have it in you to contantly try to improve things and find easier way of accomplish monotonous tasks and this seems like the right opportunity to put your creativity and smarts to use.
Following is one simple one size fits all
higher order component which you may use to display appropriately sized loading shapes regardless of the shape of the content. This technique isn’t perfect however since the HOC
requires you to have a know what a tipical instance of your content is going to be. For example a typical female name might be Jane
.
import React, { FC } from 'react'
import ContentLoader from 'react-content-loader'
export interface LoaderProps {
isLoadig: boolean;
}
const Loader: = ({ isLoading, children }) => (
isLoading
? <div
style={{
display: 'inline-block',
position: 'relative'
}}>
{children}
<ContentLoader
style={{
position: 'absolute',
width: '100%',
height: '100%',
top: 0,
left: 0,
}}
/>
</div>
: <>{children}</>
)
If you’re looking to get started with your own react application a recommended batteries included seed project is react hot starter
Lazy Loading Pages
The third type is least common of the 3, but important nevertheless. At a certain point, when one of your pages grows significantly, or when a certain page is using a large third party dependency, you might want to lazy load that page to decrease time to first meaningful paint and time to interactive.
Since the page loading skeleton will be included in your base bundle and the page itself will be loaded lazily - the page loading skeleton will be a completely separate entity.
Usually you would create a handcrafted version of a page but will all major content containers replaced with shimmering boxes. This would require you to meticulously replicate the layout of the original page and any change that you make to the original page shall require adjustments of the page loading skeleton. This is a painstaking process, but the good news is - there is an easier way.
You can separate the flash from the bone by extracting layout components into a page skeleton component which does not care too much about the gems you insert into its slots since it only knows how to position those elements. The you would use the page skeleton as the basis for creating the page component itself as well as the page loading skeleton keeping the layout in sync between the two.