How to Use Suspense and GraphQL with Apollo to Build Great User Experiences

For many app developers, GraphQL is instrumental in building great user experiences. With the introduction of React Suspense, developers have an ergonomic way to orchestrate loading states to improve upon the status quo. In this talk, the Apollo Client team will show you how we built a non-trivial application using Apollo Client’s new Suspense features, GraphQL features like the @defer directive, and how to combine them to build great user experiences in your own apps.

Rate this content
Bookmark
Watch video on a separate page
Video Summary and Transcription
The video talk explores how to effectively use React Suspense and Apollo Client to enhance user experiences in web applications. It introduces the UseSuspenseQuery hook as a suspenseful version of UseQuery, which simplifies code by removing the need for loading booleans and states, allowing React Suspense to manage loading states. This talk highlights the importance of managing suspense boundaries to optimize the loading experience, suggesting that a single suspense boundary might not always be ideal. Instead, adding multiple boundaries can provide more granular control over loading transitions. The defer directive in GraphQL is discussed as a tool to improve performance by streaming slower data parts later. Additionally, the video touches on the integration of Apollo Client 3.8 features, like UseBackgroundQuery and UseReadQuery hooks, which enhance the React 18 transitions. Testing tools like Testing Library are recommended for testing suspense functionality. The video provides practical insights into reorganizing suspense boundaries and using suspense hooks, making it a valuable resource for developers looking to leverage Apollo Suspense and Apollo UseSuspenseQuery in their projects.

This talk has been presented at React Advanced 2023, check out the latest edition of this React Conference.

FAQ

The talk focuses on using suspense and GraphQL with Apollo Client to build great end user experiences.

Apollo Client 3.8 includes new suspense hooks such as UseSuspenseQuery and features integrated with React 18 transitions.

The defer directive in GraphQL allows marking part of a query to be streamed in later, which helps load some data faster while deferring slower parts.

Testing tools like Testing Library are recommended for testing components that use suspense to render fallbacks.

Suspense boundaries can be reorganized to control the loading experience, allowing for more granular control over which parts of the UI are rendered and when.

In addition to UseSuspenseQuery, Apollo Client 3.8 also introduced UseBackgroundQuery and UseReadQuery hooks.

You can check the Apollo GraphQL GitHub repository, specifically the Spotify Showcase project, for the code and more details about the demo.

The talk does not cover React server components, streaming SSR, or implementing support for suspense in a data fetching library.

The speakers are Gerald Miller, a principal software engineer at Apollo, and Alessia Balissario, a staff software engineer at Apollo.

The UseSuspenseQuery hook is a suspenseful version of the UseQuery hook, designed to fetch data while integrating with React 18 suspense features.

1. Introduction to the Talk#

Short description:

We're excited to be here in London to talk about using suspense and GraphQL with Apollo client. We'll also discuss building great end user experiences. Let's quickly introduce ourselves. I'm Gerald Miller, a principal software engineer at Apollo, and you can find me online at Gerald Miller. I'm Alessia Balissario, a staff software engineer at Apollo, and I'm at AlessBell.

What an amazing day. We're so excited to be here with you all in London. And we're going to be talking about how to use suspense and GraphQL with Apollo client and how to build really great end user experiences. But first, let's introduce ourselves very quickly because Amber did a great job already. I don't know if anything's gonna be new said here, but I am Gerald Miller. I am a principal software engineer at Apollo working as a maintainer on Apollo client. And you can find me pretty much everywhere online at my handle Gerald Miller. And I'm Alessia Balissario. I'm a staff software engineer also at Apollo and I'm at AlessBell.

Read also

2. Introduction to React Suspense and Apollo Client#

Short description:

This talk is about reintroducing core React suspense concepts in the context of client rendered web apps and focusing on how to fetch data in suspense with Apollo clients new suspense hooks. We won't cover React server components or streaming SSR. Check out the experimental Next.js package for more information.

So let's dive right in and talk about what we will be covering today. So this talk is going to be about reintroducing, introducing or reintroducing for some of you, some core React suspense concepts in the context of client rendered web apps and focusing on how to fetch data in suspense with Apollo clients new suspense hooks that we released in August in version 3.8 of Apollo client. And also to talk about what we're not going to cover today. We're not going to be covering React server components or streaming SSR. There's, it looks like there's a lot of sessions here today. We hope that you check out for some of those super cool advances in the React ecosystem. But if you are curious about this space with Apollo specifically, you can check out our experimental Next.js package as you see on screen here. Also shout out to our co-maintainer Lens who's done a lot of the legwork for this here. So if you have questions about this, definitely hit him up. Also what we're not going to be covering is how to actually implement support for suspense in a data fetching library, because it's actually a little more complicated than meets the eye.

3. Exploring React Suspense and Loading States#

Short description:

Let's go back to 2018 when Andrew Clark highlighted the difference in loading states between native platforms like iOS and the web. React suspense goes beyond rendering loading states and provides a composable way of managing transitions. We'll be discussing suspense in the context of Apollo Client and the UseSuspenseQuery hook. Pay attention to the colored boxes on the screen, which represent areas of our UI with UseQuery hooks. Let's take a look at the loading UX.

Okay, so let's go back in time to 2018 when Andrew Clark, React core team member, sent out this tweet in January 2018. So this was more than a month before Dan Abramov's JSConf Iceland talk titled beyond React 16, which gave a look into the future of React and introduced suspense with some of the first public demos. I think this is a great place to start because Andrew here is talking about certain patterns of interaction that just felt much nicer and still do in many ways on native platforms like iOS compared to the web and the experiences that are most often seen on those platforms.

Andrew wrote, one reason iOS feels nicer than the web, fewer unnecessary loading states. Look what happens here in this screen recording when you tap an option in the settings app. Instead of transitioning immediately and showing a spinner for a split second, it pauses for a moment until the view is ready and that view slides over. Much more fluid. I think this is really prescient, was in 2018, and foretold a lot of where the ecosystem was going in terms of managing these transitions on the web.

Yeah. So, if you've used Apollo for any amount of time, you've probably used this hook quite a few times, useQuery. This is the way you typically fetch data in your applications today. This comes with really two exports that you use most of the time, the data property and the loading boolean that you use to determine when to show a loading state in your components. Just to take a look at a small example here, we've got this little albums component here that uses the useQuery hook to fetch some data and show this loading boolean. No surprise when you tap this button, you see this loading state here. When that loading boolean is true, we get that little bit. When it's done loading, we can see our list of albums here. And so while we just looked at the status quo and that flash of a loading spinner, and we will be talking a lot about loading states today, and how that impacts the UX of our apps that we're building, we really wanted to put a disclaimer out there that React suspense is not just about having a different mechanism for rendering loading states. Just a different API for showing spinners and fallbacks. It really gives us this very composable, very Reacty way of orchestrating and managing these transitions in our apps. So it goes much further than just simple loading states, if you want to think about it that way.

So in terms of Apollo Client, we're here to talk about suspense, and we're talking about suspense in Apollo Client. We're going to be talking about this in the context of a hook we released in Apollo Client 3.8, called UseSuspenseQuery. What is UseSuspenseQuery? Essentially it's a suspenseful version of our UseQuery hook that fetches some data that's integrated with all of the React 18 suspense features, which includes React 18 transitions. So for the majority of the rest of the talk we're actually going to be looking at this in the context of the Spotify clone we built here. And there's a couple of areas on screen that we'll want you to pay attention to as we go through some of these demos here. So you see all these colored boxes on the screen? Each of these represent an area of our UI that has a UseQuery hook that's loading some data from the server. This is really to get an idea of how the status quo today works, and how we can make this better with the UseSuspenseQuery hook and just React 18 suspense. So to get an idea of what the loading UX looks like today, let's go take a look at this here. Yeah, so here we see each of those four components when our app first loads. Again, they're using UseQuery under the hood, and we can see the popcorn effect as the UI loads in.

4. Transitioning to UseSuspenseQuery#

Short description:

Each component renders its own loading fallback and data as soon as the network request returns it. We're transitioning from UseQuery to UseSuspenseQuery. Let's start with the user menu component. We remove the loading Boolean and loading state as Suspense handles it. The query type becomes UserMenu query type in the Suspense enabled application. We see a blank screen briefly before the UserMenu is loaded. We'll need a SuspenseBoundary for a loading fallback.

Each component is responsible for rendering its own loading fallback, and it's going to render data as soon as its network request returns that data. We don't have any greater control over it than that, we're just letting these components render when the data is ready.

It's a bit visually distracting, having those four areas load in entirely dependent on when that network request resolves. So we're going to actually write some code together. We're going to transition this from a UseQuery-enabled app to a UseSuspenseQuery-enabled application.

So we're going to pull up this demo here, and again, like I said, this is what we will be working with today. Just to refresh, this is the exact same experience you saw in that video a second ago. That popcorn effect you see as that data loads in. And just to get oriented a little bit with this application here, here I have my layout here. You can see those colored boxes, each of those components there, the sidebar, the user menu, the route, and the playbar, which each represent one of those areas that load some data.

So we're going to start and actually convert one of these components over to UseSuspenseQuery. We're just going to start with the user menu there, which is that green box in the top right-hand corner. So to do so, here's my component, UseQuery. You see I have my GraphQL query, my UseQuery import, and a pretty familiar site here, that data and loading Booleans. When that loading Boolean is true, we return our loading state, and that's what we see.

So to convert this over to Suspense, I'm going to start by importing UseSuspenseQuery, replace the usage here, and something you're going to notice right away when we make this change is that we get this error here, property loading does not exist on type UseSuspenseQueryResult. And that's because the mechanics of Suspense, we don't actually need that loading Boolean because we're going to let Suspense handle this for us. So it makes no sense, we can actually remove that. And because of that, we no longer need our loading state. Something to also pay attention to here, with this, if I were to take a look at the type of that data property, if you're used to using this with UseQuery, you're used to seeing a union with undefined here as well. With the Suspense enable application, it actually works as if this were a synchronous code. You see our query type here is that UserMenu query type, which is really neat, enables some nice things about this. For this demo, we want to make a change. We like to take baby steps and kind of see what that change does to our application. So let's go back to our application here and refresh it and see what that change did.

Okay, so now we're seeing a blank screen for a split second, and at first paint we see the UserMenu was loaded in there. It was pretty quick, so maybe we can refresh again, Gerald. So you won't see the green highlight around the UserMenu in the top right because by the time our app first renders, the data is present for that UserMenu. So we're fetching the data for our UserMenu with our SuspenseEnabled hook, but we're not showing a loading fallback yet. For that, we're going to need a SuspenseBoundary.

5. Adding Suspense to Components#

Short description:

Let's add suspense to our components one by one. We start with the UserMenu component, wrapping it with the Suspense component and using the UserMenu loading state as the fallback. After refreshing, we see the green highlight around the UserMenu in its loading state. Now we'll add suspense boundaries and use suspense query to the sidebar and Play bar components. We replace the imports with useSuspenseQuery, remove the loading boolean and state, and make the necessary changes in the layout.

So let's go ahead and add that, Gerald. Let's do it. So I'm going to come over here to my layout, and to add suspense, I'm going to import the Suspense component from React. And then we're just going to wrap this, our UserMenu, here with that. If I can hit the right screen, this is the problem with being so tall on this here. And this is going to take a single prop, which is the component we want to show when the component is suspended. So here, I'm just going to use that UserMenu loading state here. And again, baby steps. Let's go ahead and refresh and see what this change did here.

Great. So now we see the green highlight around the UserMenu as it's in its loading state. But otherwise, everything else is unchanged. I mean, the entire UX is still totally unchanged, right? So let's go ahead and add suspense boundaries and use suspense query to our other three components before we can make a bit more progress here. Awesome. So I'm just going to start in. We'll go to the sidebar here. Same thing that we did with the UserMenu. I'm going to replace my import with useSuspenseQuery. We don't need that loading boolean anymore, which means I can get rid of that loading state in my component. We'll do the same thing with the Play bar here. useSuspenseQuery. Go replace the usage, get rid of the loading boolean. And hopefully you're starting to see a little bit of a pattern here. One of the things we wanted to make sure to do with you suspense query is make it feel very familiar to useQuery in that it's got a lot of the same options and kind of feel that it does. Obviously, the ergonomics of how you manage that loading state is a little bit different. But we're hoping in the majority of cases, switching over to suspense is more or less as easy as this is. So let's get our last one here. useSuspenseQuery. Get rid of the loading boolean. And then in our layout, we're going to add our suspense fallbacks around each of these.

6. Optimizing the Loading Experience#

Short description:

I'm just going to copy this a bunch of times. And then let's make sure each of these use the right loading states here. This one is the play bar. Thank goodness for prettier, otherwise my code would look horrendous. Suspense is not a magic wand that we can wave at our code and have the UX improve. But now that all of our components are using suspense to show those fallbacks, we have a superpower here because we can reorganize these suspense boundaries. Let's make the first real substantive change here to the loading experience by wrapping our entire app in a single suspense boundary instead of those four granular boundaries for each component. So we have a single update to the screen now, just by virtue of being able to move that suspense boundary to the outermost level of our app. But now let's say we're starting to interact with our Spotify clone here. We want to listen to a different playlist. We see something interesting, which is that I see that suspense fallback show up when I navigate to another route here. We've gone a bit too extreme in one direction of having a single suspense boundary for our whole app. By transitioning the route, that transition and that network requests to fetch a new playlist is triggering that single suspense fallback for our entire application. Obviously, that's not the user experience we want here.

I'm just going to copy this a bunch of times. And then let's make sure each of these use the right loading states here. This one is the play bar. Thank goodness for prettier, otherwise my code would look horrendous.

Okay, so again, baby steps. Let's go refresh this and see what happens. And it's a bit anticlimactic because still nothing has changed, right? Suspense is not a magic wand that we can wave at our code and have the UX improve. All we've done is change the mechanism that we're using to render, to display that loading fallback, to be suspense instead of having our components be responsible for rendering those loading fallbacks.

But now that all of our components are using suspense to show those fallbacks, we have a superpower here because we can reorganize these suspense boundaries. And so let's make the first real substantive change here to the loading experience by wrapping our entire app in a single suspense boundary instead of those four granular boundaries for each component. Awesome. So, like before, I'm going to add a suspense boundary here. This time it's going to be around my entire application. Make sure I use the right loading state here. I'm just going to go delete all of those suspense boundaries that we added before. So now here we have a single suspense boundary around the whole thing. Let's see what this change does to our application here. Ah, tada. So we have a single update to the screen now, just by virtue of being able to move that suspense boundary to the outermost level of our app. And I must say, that's much more pleasing to the eye, having a single paint to the screen with all of our data ready for the user to interact with.

But now let's say we're, you know, we're starting to interact with our Spotify clone here. We want to listen to a different playlist. Gerald why don't we go ahead and navigate around and pick something else to listen to. Yeah, that's great. So my daughter would be psyched if we all listened to her playlist together. So I'm going to navigate here and we see something interesting, which is that I see that suspense fall back, show up when I navigate to another route here. So what might be happening here, Alessia? Yes. So we've gone a bit too extreme in one direction of having a single suspense boundary for our whole app. So by transitioning the route, you know, that that transition and that network requests to fetch a new playlist is triggering that single suspense fallback for our entire application. And, you know, obviously that's not the user experience we want here.

7. Adding a Second Suspense Component#

Short description:

We add a second suspense component around our route to maintain the persistent layout while the inner route component suspends. When we refresh and navigate back to our react advanced playlist, the outer shell of our application unsuspends first, followed by a slight delay while fetching the route component. If the inner suspense boundary is ready to render before the outer suspense boundary, React coordinates the timings. We use the at synthetics directive in our queries to understand the timings. Deleting the synthetics directive and refreshing the page shows the effects of faster playlist route loading.

We want to keep that application Chrome, that sort of persistent layout on the screen while our user navigates around and the inner route component suspends. So let's add a second suspense component around our route. Awesome. So I'm going to come in here around the route, which is that component that suspends as we navigate around. Make sure we're using the right component here, route loading state. Let's go into refresh and then we're going to navigate back to our react advanced playlist here. And now we can see where we're back to the user experience that we're looking for. Nice. Yep. This this looks great. And so here we see that, you know, now when we load in our our outer shell of our application unsuspends first, and then there's another slight delay while we continue fetching the route component, which then unsuspends with its data when it's when it's ready to render. But, Gerald, what if the inner suspense boundary, that route components has its data and is ready to render before that outer suspense boundary? Yeah, that's a great question. Invert that. Yeah. Yeah. So to control kind of these timings here that we can see, I'm just going to point out that something you'll notice in our queries here, we're using this at synthetics directive here just to better understand how each of these timings work. So again, we want to see what happens if that playlist route actually loads much faster than our outer shell. So I'm going to delete this synthetics directive and let's go ahead and refresh and see what happens here.

8. Optimizing Loading Experience with Defer Directive#

Short description:

If our inner route component is ready to render before the outer shell, React can coordinate that for us. In the worst case, we'll have two updates to the screen, but in the best case, we'll have a single update. We can improve the loading experience by using the defer directive in GraphQL. This allows us to load some data faster and stream in slower parts later. When our route component is slower, we still see two updates to the screen.

Okay. So if our inner route component is ready to render before the outer shell, now by virtue of using suspense, React is able to coordinate that for us and orchestrate that. So we'll never see the inner suspense boundary before the outer, but it means that, you know, now in the worst case scenario, if our inner route is ready a bit later than our application shell, we'll have two updates to the screen. But on the other hand, in the best case scenario, when it's ready, you know, around the same time or earlier, we'll have a really nice single update to the screen in the best case scenario. And all of that is just by virtue of the power of suspense and using these tools that React gives us, which is really nice.

So now let's see if we were to load some more tracks here. Yeah, actually, first I'm going to go to each of these components, because you probably saw synthetics directives around each of those, and we want to get a better feel for what the actual end user experience is going to look like here. So I'm just going to go to each of these queries. I'm going to delete this here. We'll go to the play bar. Same thing, just get rid of this synthetics directive. We don't want it anymore. And now we see the loading state is much more as you'd expect. There's actually something, though, to point out here, which is that if I refresh this, that playlist that we see here is actually still taking a little bit too long for our liking to load this here. And we want to improve this experience. Now we've done some stuff with suspense, but we also want to do some stuff with GraphQL because GraphQL also gives us some great tools here. So I don't know how many of you have watched any of the spec advances lately, but there is a new stage two directive that is almost ready for mainstream called defer that lets us mark part of our query as something that can be streamed in at a later time. So it gives us the ability to say, Hey, we understand that there might be a slow part of our query here, but we want to get some data faster. And then we'll load in some of that, that slow stuff later. So just pretend we've done some sleuthing and we see that our tracks a field here is the thing that's really taking kind of the longest to load in here and what we'd like to see, we're okay if that tracks loads in a little bit later, but we'd like to see that playlist details just a little bit quicker here so we can use defer. I'm going to use an inline fragment here and let's go ahead and refresh that and see what what defer gives us here. Okay, nice. So now we saw two updates to the screen. We saw that our route component was rendered at the same time as our application shell and those deferred tracks loaded in that second render to the screen, but Gerald, what happens now if our route component is a little bit slower?

Yeah, that's a great question. So let's go back and add our trustee synthetics directive here, if I can spell timeout correctly. Let's add a second latency to this and refresh and see what happens here. Let's try that again. Got to love conference WiFi, right? Or maybe I didn't even save it. Okay, well, what we're still seeing is two updates to the screen. Conference WiFi, I tell you.

9. Optimizing Loading Experience with Transitions#

Short description:

Adding additional layers of suspense boundaries and loading fallbacks gives you more granular control over loading UX state transitions. We integrated suspense hooks with React 18 transitions to improve the loading experience. By using transitions and removing synthetic directives, we can avoid suspense fallbacks and keep the existing UI on the screen. Today, we learned how to migrate data fetching hooks to use suspense query, optimize the loading experience by moving suspense boundaries, use defer to add additional fallbacks, and mark network requests as transitions in React.

Let's see here. Okay, we're still seeing those two updates to the screen. But if our timeout on the route component on our playlist query there was working, what we were going to show in this moment was the change in UX from going to two updates to the screen in the worst-case scenario to three updates to the screen in the worst-case scenario you can imagine our application shell loads in first, then we would have the route component that would unsuspend in a second render to the screen, and then the tracks that are wrapped in defer would be that third update to the screen. So the main takeaway here is really just this idea that adding additional layers of suspense boundaries and loading fallbacks gives you more granular control over this loading UX state transitions in general in your app. But there's a trade-off here. We can show some content sooner to the users in the best-case scenario, but in the worst-case scenario we're going to add additional moments in our app where we're showing loading fallbacks in the worst-case scenario.

So one last thing, we mentioned at the beginning that we integrated the suspense hooks with React 18 transitions. We're going to take a look at that here. Here I have my playlist. I'm going to scroll down because I want to listen to more tracks at the bottom. We see something interesting here, which is that as I scroll and I go to load more tracks, we see that it suspends again and I get a loading fallback here. So how might we look to make this better? Something to point out here is in my playlist, for those of you that have used Apollo for any amount of time, you've used the fetch more API to load data in a paginated query. In this case we're doing an infinite scroll scenario. We've got a fetch more exported from use suspense query that we're calling in this handle load more function. When we call fetch more, it's causing our component to suspend again because we're going back into that loading state. We're going to make this a little bit better by bringing in a transition that allows us to see what we have on screen and avoid that suspense fallback. Before I do so, let's also remove the synthetic directives since we don't want to wait two seconds to load more tracks. To add a transition, I'm just going to import the start transition API from React and we're going to wrap my fetch more call in start transition. This is going to tell React to mark this as a transition. When this component suspends, it's going to leave what we see on screen and avoid seeing that fallback. Let's go ahead and refresh. We'll scroll down here and now we get the UX that we are expecting. Much better. So, what did we learn today? We looked at our Spotify clone starting with use query under the hood and then migrated our data fetching hooks over to use our new suspense enabled hook use suspense query. Then we saw how moving around suspense boundaries in our app could change, drastically impact the loading experience. And then we looked at how to use defer to add additional fallbacks and, you know, deprioritize some of the fields in our query. Then we saw how to mark one of our network requests coming from our fetch more call here as a transition in react to tell react to keep the existing UI on the screen while we make that network request in the background. So that's our demo for you today. Yeah, thank you. Thank you.

10. Conclusion and Future Plans#

Short description:

We didn't get to talk about the whole suspense story. We released two other hooks in Apollo client 3.8, use background query and use read query. In the future, we're working on Apollo client 3.9 with new APIs like suspenseful use fragment and lazy use background query. The code for this application is available in the Spotify showcase repo. Thank you for having us.

Awesome. So, real briefly, we are out of time but unfortunately we didn't get to talk about the whole suspense story. We also released two other hooks in Apollo client 3.8, use background query and use read query to help avoid request waterfalls. So if you're interested in those, check out our documentation or come talk to us after our talk here. Yes, and looking to the future, we're currently working on the next minor version of Apollo client 3.9, which we have planned some exciting new APIs, like a suspenseful version of the use fragment hook, and also a lazy version of use background query that we're calling use interactive query for preloading, prefetching data on some user interaction. If you liked the demo that you saw here today and want to play around with it yourself, feel free to go to this repo, the Apollo GraphQL org, the Spotify showcase, the code for this entire application lives there. And we are planning to use this as a teaching tool and a way to show off some Apollo client best practices, but also as maintainers, we're going to be using it to kind of stress test our own APIs to just really get a feel for what it's like to use it in a complex application. But with that, thanks so much for having us up here. Yeah, thank you.

QnA

Testing Suspense and Single Suspense Boundary#

Short description:

To test suspense in a component, use popular React testing tools like testing library. The philosophy is to test the app as users would expect, so the loading state remains the same. Using a single suspense boundary at the top level may negatively impact perceived performance, but additional boundaries can be added. Each component doesn't necessarily need a loading state, and the user menu loading state pattern is a syntactic sugar for non-suspense.

So let's start with the first one right in the middle here. Okay. So, first one, how would you go about testing suspense? Great question. So I guess it depends on, I'm assuming this person's talking about, like how would you go about testing a component that's using suspense to render its fallback? And the answer is really using the testing tools that are super popular and ubiquitous in the React community, like testing library.

Yeah, to keep my answer short, anything to add? Yeah, I'll just add there, so one of testing library's philosophies is to use the app as your users would expect. So presumably you're already testing some kind of loading state in your application. You know, does my component render whatever spinner or loading text or whatever you have? It's going to be the same thing. It's just your code in that component is going to be organized a little bit differently. But if you're using it as kind of that black box, like the end user experience, really there's not a whole lot to change. Thank you.

And this may be our final question, but again, you'll be able to speak to them around the corner. So final question, how does using a single suspense boundary at the top level affect things like SCP and LCP? And can this be answered in two minutes? Yeah, great question. So the short answer is you probably don't want just a single suspense boundary in your application. You know, maybe there's a certain kind of app that, you know, where you really want to wait for every single initial network request resolved before showing anything at all to the user. the benefit of being able to use that super Reacty composable API that allows you to just compose these things really nicely. So yeah, so again, you would probably if you had a lot of network requests happening in your app and just a single suspense boundary, yeah, that could definitely negatively impact your sort of perceived performance in loading UX, but that's why it's super simple to drop in additional boundaries. Yeah. I think we can squeeze in one more. What do you reckon? Let's do it. Why not? Let's do it. Okay. So you used a user menu loading state pattern. Does every component have a loading state? How does this scale? This seems like a syntactic sugar for non-suspense. Yeah, so that's just the way really I chose to structure this for this demo because it's the easiest to remember. I didn't have to deal with imports because that takes time obviously to write in front of you all. So really, I would say it's up to you, whatever pattern you have today, again, the biggest change we had is we took that loading state that was rendered in our component and we moved it up to a suspense boundary. But I don't know if you noticed that each of those components that rendered with the use query, if loading used that same user menu dot loading state component inside of there. So I really didn't change what component I was using. I just moved it to the suspense boundary rather than rendering it in the component. But again, that's just a pattern I chose specifically for this talk.

Customizing Loading States#

Short description:

It's up to you. However that works in your app. In this application, we have different loading states, but in your case, it may only be one component. It depends. Thank you for your talk.

It's up to you. However that works in your app. Again, in this particular application too, we've got so many different loading states because they're skeleton screens, but if you've got a single spinner that you use in your application, that may only be one component. So yeah, again, it's with the classic, it depends.

Wow. It is 11.10 on the dot. All right. So much. And we're the timekeeper as well. So thank you so much for your talk.

Jerel Miller
Jerel Miller
Alessia Bellisario
Alessia Bellisario
29 min
20 Oct, 2023

Comments

Sign in or register to post your comment.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

A Guide to React Rendering Behavior
React Advanced 2022React Advanced 2022
25 min
A Guide to React Rendering Behavior
Top Content
This transcription provides a brief guide to React rendering behavior. It explains the process of rendering, comparing new and old elements, and the importance of pure rendering without side effects. It also covers topics such as batching and double rendering, optimizing rendering and using context and Redux in React. Overall, it offers valuable insights for developers looking to understand and optimize React rendering.
Building Better Websites with Remix
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a web framework built on React Router that focuses on web fundamentals, accessibility, performance, and flexibility. It delivers real HTML and SEO benefits, and allows for automatic updating of meta tags and styles. It provides features like login functionality, session management, and error handling. Remix is a server-rendered framework that can enhance sites with JavaScript but doesn't require it for basic functionality. It aims to create quality HTML-driven documents and is flexible for use with different web technologies and stacks.
React Compiler - Understanding Idiomatic React (React Forget)
React Advanced 2023React Advanced 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
Top Content
Watch video: React Compiler - Understanding Idiomatic React (React Forget)
Joe Savona
Mofei Zhang
2 authors
The Talk discusses React Forget, a compiler built at Meta that aims to optimize client-side React development. It explores the use of memoization to improve performance and the vision of Forget to automatically determine dependencies at build time. Forget is named with an F-word pun and has the potential to optimize server builds and enable dead code elimination. The team plans to make Forget open-source and is focused on ensuring its quality before release.
Using useEffect Effectively
React Advanced 2022React Advanced 2022
30 min
Using useEffect Effectively
Top Content
Today's Talk explores the use of the useEffect hook in React development, covering topics such as fetching data, handling race conditions and cleanup, and optimizing performance. It also discusses the correct use of useEffect in React 18, the distinction between Activity Effects and Action Effects, and the potential misuse of useEffect. The Talk highlights the benefits of using useQuery or SWR for data fetching, the problems with using useEffect for initializing global singletons, and the use of state machines for handling effects. The speaker also recommends exploring the beta React docs and using tools like the stately.ai editor for visualizing state machines.
Routing in React 18 and Beyond
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Routing in React 18 brings a native app-like user experience and allows applications to transition between different environments. React Router and Next.js have different approaches to routing, with React Router using component-based routing and Next.js using file system-based routing. React server components provide the primitives to address the disadvantages of multipage applications while maintaining the same user experience. Improving navigation and routing in React involves including loading UI, pre-rendering parts of the screen, and using server components for more performant experiences. Next.js and Remix are moving towards a converging solution by combining component-based routing with file system routing.
(Easier) Interactive Data Visualization in React
React Advanced 2021React Advanced 2021
27 min
(Easier) Interactive Data Visualization in React
Top Content
This Talk is about interactive data visualization in React using the Plot library. Plot is a high-level library that simplifies the process of visualizing data by providing key concepts and defaults for layout decisions. It can be integrated with React using hooks like useRef and useEffect. Plot allows for customization and supports features like sorting and adding additional marks. The Talk also discusses accessibility concerns, SSR support, and compares Plot to other libraries like D3 and Vega-Lite.

Workshops on related topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
Concurrent Rendering Adventures in React 18
React Advanced 2021React Advanced 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
Maurice de Beijer
Maurice de Beijer
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React, TypeScript, and TDD
React Advanced 2021React Advanced 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Web3 Workshop - Building Your First Dapp
React Advanced 2021React Advanced 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
Nader Dabit
Nader Dabit
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn