Although still considered experimental, React Suspense is certainly worth trying, even if for smaller personal projects.
Suspense helps control component life cycles declaratively and prevent race conditions, among other things.
Using Suspense and hooks, we can write clean and functional code to manage state and handle errors while fetching GraphQL data.
Overview of React Suspense
One of the primary use cases of Suspense is managing the application state during async operations. With Suspense, you avoid writing annoying imperative code, like conditional rendering, and try/catch statements inside of your components.
Another well-known use case is code-splitting , but we won’t cover it in this post.
In a typical modern UI, there are tons of things to take care of when fetching data. You have to toggle loaders, prevent race conditions, and maintain the correct order of events. Suspense makes all of it infinitely simpler. Here’s how you would typically use React Suspense:
|
|
One interesting thing you might’ve noticed is that we create an initialResource
object right when the app loads. So what is this resource anyway? Let’s briefly cover resources, they are pretty important.
Resources are sources of async data for Suspense. Under the hood, a resource is simply an object that has a read
method. React Suspense will call that method as needed for its inner workings.
So what exactly does Suspense do for us?
Notice how we call resource.user.read()
without any safe checking. Getting user info is an async process, yet we’re using the resource synchronously because we know that Suspense will take care of fetching and checking the data. All we need to do is provide Suspense with a fallback
component.
This approach makes our application cleaner and more robust by eliminating the need for safe checking and conditional rendering and preventing race conditions.
Suspense with GraphQL
We’ll build a simple app that displays SpaceX rocket launches using their public
GraphQL endpoint
.
We’ll be using Apollo client , just because it’s much easier to work with in my experience. But you could do the same thing using any other GraphQL client.
Adding apollo client
First, let’s set up our Apollo client that we will use to send queries.
|
|
Adding graphql query
Now we will add the query for fetching launches. To follow good practices, we’ll store it in a separate file:
|
|
Factory function
This is where Suspense comes into play. Let’s make a factory function that accepts a GraphQL query and returns a resource:
|
|
Our factory function tracks the status and the server response of the async request. We also have a suspender
that stores the GraphQL query promise. When we hear back from the server, we update the status
and result
variables.
So the factory function returns a resource, and, as I mentioned, a resource is simply an object with the read
method. The read
method does the following:
- If the status is pending,
read
throws thesuspender
promise, which Suspense will catch and display thefallback
component. - If the status is
completed
,read
returns the result. - If the status is
error
, ‘readthrows the
result`, which, in that case, is an error instance.
Believe it or not, that was the most complex piece.
useAPI hook
Strictly speaking, we could start using wrapGraphql
directly without wrapping it into a hook. But a custom hook is a nice abstraction and is handy if we decide to add things later, like checking session status or permissions before sending a request.
|
|
The code for useAPI
is straightforward. The hook accepts a query and uses the wrapGraphql
factory function to return a new resource.
Finally, here’s how we would use it:
|
|
Conclusion
As a side note: we used Apollo for the GraphQL client, however, another alternative to consider is Relay . Relay is closely integrated with React Suspense and could be a better choice for you. With that said, it’s also much more opinionated, and I find Apollo easier to use.
That’s it for this post. We used React Suspense with GraphQL, but you can certainly adapt it to work with any other async source. Suspense also has more applications than just handling async operations. The best place to begin your learning is the official Suspense overview doc.
Here’s a link to the codesandbox for this tutorial.
If you’d like to get more web development, React and TypeScript tips consider
following me on Twitter,
where I share things as I learn them.
Happy coding!