When I saw the article 'Stop using isLoading boolean' written by Kent C. Dodds my first thought was - what's wrong with isLoading
boolean? Why shouldn't I use it? Then I read it. And saw his point.
It is a common practice to use isLoading
boolean to show some placeholder or spinner when data in our app is loading. This is fine - you set isLoading
to false
, change it to true
when data is loading and when data is here - put it back to false
. But what happens when error occurs? Data is not loading but there is no data to show either. We start to add more conditions - first not loading and no error, then for not loading but with error, another one for loading. Do you see the point?
What Kent suggests in his approach is having status with different enum values for every case e.g. 'idle'
, 'resolved'
, 'rejected'
. In the code then we can go like (examples based on the article that I mentioned earlier):
if (status === 'idle') {
return <div>Data is loading...</div>
}
if (status === 'resolved') {
return <div>{Fetched data}</div>
}
if (status === 'rejected') {
return <div>Something went wrong!</div>
}
Thanks to that we can set status for particular case after every activity and there is no need for double conditions (like is not loading and there is no errors etc).
To get rid of equal signs we can put status info in variables.
const isLoading = status === 'idle';
if (isLoading) {
return <div>Data is loading...</div>
}
And that's it! I recommend reading Kent's article for deeper explanation and more examples.
Latest comments (43)
In my opinion you are over simplifying what in reality is mostly a complex matter. To begin with, you might be responsing to a particular article, but in your own standalone article you are not specifying what action you are performing for which you are calling the isLoading status in the first place. I can only infer you are refering to a fetch operation, given the scenrios you lay out. But isLoading is used in many different use cases that have multitude of scenarios of different complexities. You could be loading a new view, refreshing part of the UI, loading pre-fetched data, calculating post action etc. isLoading as boolean is very valid for those many scenarios, and does not correlate to response statuses.
Other than that, isLoading is self-indicative by its name, while the other statuses you exemplify are more abstract in meaning and require closely-coupled context to know how to use them. Self-indicating statuses are to be appreciated, even being boolean. The verbosity of having to check multiple statuses together in order to know how to act on them is not a bad thing, is not anti-pattern, and I'd even dare say they are desired. In the end of the day, we all just want clearly read code, especially when it's someone else's.
I am not saying that isLoading is always bad. I just wanted to share what I learnt in the article I mentioned. That is really interesting to me because earlier I really didn't even think that in some cases isLoading boolean may be not the best choice
If you don't want to add extra words - "idle"
Just consistent with the state of the JavaScript Promise.
It is my opinion that every developer who implements a Boolean isLoading is not a competent developer.
Good tip this is a great way to deal with it.
If you are into functional programming, this is the perfect situation for using a union-type. There are some great libraries in typescript to implement union-types. I am using @practical-fp/union-types, check it out!
github.com/practical-fp/union-types
I made a package around this idea for Vue.
github.com/c5n8/vue-use-async-hook
The challenge is to name the state when we have not called the function for the first time. I call it standby, but I think it could be better.
Also, if only Javascript/Typescript has implicit member expression like Swift, we could eliminate these space hogging strings, masquerading as a pseudo enum.
This article makes me feel very (type) unsafe. But seriously, I would not recommend this route unless
The big issue I have is the inevatable instance where you spell 'loadng' instead of 'loading' and your logic breaks. This can be avoided using union types in typescript of creating an enum with regular JS.
That's why we should all move to TS :) oh and also I'd recommend union types instead of enums
It might be great for some situations but more verbose for others...
Let me explain.
Normally (in React, but I guess it would be almost the same elsewhere) I would import the fetch logic like this:
const [isLoading, Data, isError, Error] = GetData(URL)
Then in the JSX:
My point is that the booleans make it possible to use really short syntax.
I definitely see your point when status could have a lot of different states, but if you have a lot of different skeleton loaders and stuff I think booleans are hard to beat.
why not return the different states like booleans?
something along the lines:
In Typescript I always use enums for that :)
Thanks for the tip and for sharing!