DEV Community

Cover image for Stop using loading spinners

Stop using loading spinners

Fernando Rojo on October 10, 2021

Skeletons are better than spinners. If you're refreshing data, or fetching more, show a spinner. But a screen with no data feels less empty with a ...
Collapse
 
cstrnt profile image
Tim Raderschad

I think it will be a long way to convince the whole world to switch over from spinners to skeletons haha. But I think that it will be easy with such good libraries like moti.

Also: what your opinion on prefixing boolean variables with is or has? I always find it much easier to read isLoading instead of loading

Collapse
 
nandotherojo profile image
Fernando Rojo

I’ve seen isLoading used a lot. I agree that it’s more descriptive. For some reason I just like shorter words without camel case, but I definitely see the merit to isLoading.

Collapse
 
reikrom profile image
Rei Krom

Prefixing a verb with "is" signals that it's a state/Boolean.
Naming something with just a verb could be confused with a function.

Using shorter words when working on your own is fine, if you're part of a team going against established conventions makes it a pain for everyone else.

Thread Thread
 
nandotherojo profile image
Fernando Rojo

I’m not sure if ‘loading’ would ever be considered a function. You’re free to add ‘is’ there if you want.

Collapse
 
zwacky profile image
Simon Wicki

I'm pro-skeleton placeholder.

But Google’s June 2021 update made us reduce our skeletons drastically due to Cumulative Layout Shift (CLS).

Some of our components weren't matching the height of the skeletons.
The CLS happened when a user navigates to a different view and the response caused the content rendering after the grace period of 500ms. We saw this happening a lot by Indian users with mobile data.

And this prevented us from getting all green URLs for the Core Web Vitals.

We stopped using skeletons for each component and moved to a skeleton per page model.
The height of the skeleton was big enough, that re-rendering it even after the 500ms grace period wouldn't cause any CLS.

Problem solved and we got all the green URLs. ✅

Collapse
 
amirault profile image
Tony Amirault • Edited

Hello thank for this very interresting article!

After testing some cases i find out that

export type LoadingProps<PropsOnceLoaded> =
    | ({ loading: true } & Never<PropsOnceLoaded>)
    | ({ loading: false } & PropsOnceLoaded)
Enter fullscreen mode Exit fullscreen mode

Allow us to access to the root of PropsOnceLoaded and not the subfields.
Why allowing root access ? why usingNever<PropsOnceLoaded> instead of just using { loading: true } without it ?

What do you think about this one ? seems more convenient for me, don't you think ?

export type LoadingProps<PropsOnceLoaded> =
    | ({ loading: true })
    | ({ loading: false } & PropsOnceLoaded)
Enter fullscreen mode Exit fullscreen mode

In this way you can't access to the root of the PropsOnceLoaded

Thank you in advance for your response!

Collapse
 
nandotherojo profile image
Fernando Rojo

This is a fantastic question. The reason is, this way you can destructure your props in the component. Try doing it your way, and then see what happens to TypeScript in the component if you try to destructure props.artist.

By using never or undefined, we allow ourselves to at least see the destructured variables in the component.

However, you are correct. Your example is the safest. You’ll just have to make sure that you always check for props.loading before using props.artist.

Since my example fixes this at the consumption step of the component, it isn’t technically needed.

Hope that helps!

Collapse
 
joshuaamaju profile image
Joshua Amaju

I don't understand where you guys get this weird ideas, not that I don't know what skeleton placeholders are. Sacrificing bundle/app size just to add some fancy loader that doesn't really make much of a difference in the long run.

Collapse
 
walkeryr profile image
Yuriy Khamzyaev

Thanks for the great article, it was also really nice to learn about usage of TypeScript unions for handling down conditional props

Collapse
 
nandotherojo profile image
Fernando Rojo

Glad it’s useful!

Collapse
 
scottlexium profile image
Scottlexium

Am a visual learner and this looks simple though I would prefer you had a video for it.