With the release of the Hooks API into
React new opportunities arise to eliminate even more boilerplate. The one I want to talk about here is
If you don’t know it, you should check out the official page. To describe it shortly, it’s a component, like any other, which takes two props :
Promiseof a component to render, once it’s available.
- A loader component to display until the promise is fulfilled.
The use case most people write about involves the
import(...) syntax. But that’s not what I’m after here. I will argue that you should use
Suspense instead of
useEffect in most cases.
Say you have a user ID and want to fetch the associated username. One such component could look like this :
The problem I see in this code could be described as a hidden dependency. You need the
getUsernamecall to work but in the end, you are stuck if it did not. You also make this component impossible to test and reuse elsewhere. The
getUsername call cannot be mocked or replaced, the server needs to exist.
In other words: the component has multiple responsibilities (fetching and displaying) and creates a coupling between what is displayed and the server we are talking to.
A simple change would be to make the dependency explicit.
By having the username directly as a prop we remove the coupling between this component and the server and extract one responsibility from the component.
But we still have a problem on our hands. Our prop is a
Promise, not just data. This means our component still has to wait until the promise is fulfilled, displaying a loader while it’s not.
This is cumbersome as it leads to the multiplication of
undefined checks, which worsen with every call we need. Even worse, it’s hard to switch between loaders as nothing is centralized and code is crammed with boilerplate.
Let’s simplify even further: we just take raw props and remove the
Of course, this whole logic didn’t disappear. Here is the call to our component’s last version, with
User being our component.
At this point, you may ask yourself why we even bother. It looks exactly the same. Keep in mind that, in real-life conditions, the
User component would have internal states, on top of which more complex rendering logic would be built.
Now, however, since we have extracted the fetching part of the component, we can abstract it over and reuse it.
With this very simple wrapper, let’s call it
Lazy, here is our new
User component call.
At this point, we have a unified way of fetching data for one component to render. But then, do we need to copy/paste this piece of code in all our projects? And what about multiples props? And passing a
Component inside a callback is ugly, do we have to?
To all these questions I would say: do you still remember the title of this article? Yes, it’s time we bring in
Suspense. Here is our previous component but replacing our own
Lazy with the power
React offers us.
Suspense we get a unified way of handling our data fetching, without having to write our own little wrapper for every project. It also lets us think of components as data, but that’s for another article.
Now, last but not least: how do we support multiple async parameters? Can it work with async components (using the
imports(...) syntax)? What about both?
We could definitely handle all these cases. If you try you’ll notice things quickly become hard to read. To avoid it, allow me to introduce my Lazy-Props library with an example :
We have once again noticed the importance of separating data fetching and display to have testable and maintainable components. One solution would be to write our own wrapper to handle the data fetching, but
React now provide us with one :
Suspense. To ease its use in complex cases you can combine it with the Lazy-Props library, but in the end, Suspense is all you need.