Suspense for Data Fetching: How to Fetch During Render

Rate this content
Bookmark

What is suspense for data fetching in React? Why does React's model make creating network requests during render so difficult? Why does (to the presenter's knowledge) no library besides Relay support this, despite its sheer convenience?


In this talk, Robert will discuss how React renders components (especially with regards to Suspense), and how to build a data-fetching library that functions correctly in light of those behaviors. Then, with all the pieces in place, we'll use a library, @boulton/react-disposable-state, to roll our own suspense-compatible data fetching!

5 min
15 Nov, 2023

Video Summary and Transcription

This talk discusses the best practices for fetching data during the initial render of a component in React. It emphasizes the importance of fetching in advance and avoiding fetching twice. The talk also highlights the need for an external cache to store information about API calls and the use of a cleanup function to avoid memory leaks. Additionally, the speaker mentions their library, react-disposable-state, which can be used for making side effects during render.

Available in Español

1. Fetching Data During Initial Render

Short description:

In this talk, I'm going to discuss how to fetch data during the initial render of a component. Fetching during the initial render is preferable to fetching in an effect. Fetching in advance is better than fetching during render. Sometimes, fetching during render is the best option. Fetching is just an example of a side effect that should be performed only once and must be cleaned up. We want to avoid fetching twice and instead reuse the same network request. We could perform other side effects like firing off analytics or crunching numbers on the server.

♪♪ In this talk, I'm going to discuss how to fetch data during the initial render of a component. But before we get to how to fetch during render, we should first discuss why. Why do we want to fetch data during render? Well, we fetch data because we need it to show the user something useful. Duh. But why make the network request during render? Well, the sooner we fetch, the sooner we can show the user what they want to see and the better user experience we can provide. So fetching during the initial render is preferable to fetching in an effect, which necessarily occurs after a component initially renders, sometimes far later.

But is that the best we can do? What about fetching in advance? Consider a button that, when clicked, shows a modal, which needs data. We could start the network request when the user clicks that button, meaning that the network request will start before the initial render and we'll be able to show the relevant content to the user even sooner. That's awesome. Okay, so fetching in advance is better than fetching during render. So why fetch during render at all? Well, in some cases, it's the best you can do. Consider a modal that is shown based on some opaque function of some hard-to-reason-about redox state. Basically, we don't really know why this modal is shown or under what conditions. And in situations like that, it might be difficult to determine an appropriate moment to start that network request. So the best we can do is to fetch during render. As an aside, nothing in my presentation is really about fetching per se. Fetching is just an example of a side effect that should be performed only once and must be cleaned up.

Now, the cleanup we want to do for fetching is to garbage collect the data we received from the network if the UI no longer needs it so that on low-end devices, we avoid running out of memory. But more generically, if a component renders twice, we want to avoid fetching twice and instead reuse that same network request. So another side effect that we must perform is to know somewhere that we've already made an identical network request. And the cleanup we want to do is to, after, let's say, 30 seconds, remove the item from the cache because next time we render that component, we do actually want to make a network request. So what are some of the other examples of side effects we could perform like this? Well, we could fire off some analytics. We could have the server start crunching some numbers we're going to need later. Those are pretty much everything I'm gonna say about fetching during render applies to those as well.

Okay, so now we can finally get to how to fetch during render. Let's keep it simple. Can we just make the darn API call during the render function? Well, unfortunately, React and Cloud Components render function multiple times. And on the second render, we'd really like to reuse that previous network request. So can we use hooks? Well, unfortunately not. If your component renders, suspends, and renders a second time, all hooks will be created anew for the second render.

2. Making Side Effects During Render

Short description:

We cannot use state or refs to store information about the API call. The fact that a network request exists and should be reused has to be stored in something that outlives the render function. Making side effects only during the initial render requires an external cache. The cache should behave in a way that clears and disposes the item after a timeout to avoid memory leaks. If a component renders and mounts, it should not be garbage collected, and React will execute a cleanup function when the component unmounts. With these three principles, you can safely make side effects during render. Check out my library, react-disposable-state, on the Isograph github repo.

So we cannot use state or refs to store information about the API call. So the fact that a network request exists and should be reused has to be stored in something that outlives the render function. Which could be props, context, or a global object. This leads us to our first principle. Making side effects only during the initial render requires an external cache.

Okay. So let's discuss how this cache should behave. Consider that modal. We render it. It suspends, meaning that React calls its render function, but does not modify the dom to show the component to the user. Then, before the component commits, the entire tree unmounts because the user navigates to another screen. In this situation, React will give us no indication that the component will never mount. So when we initially place the item in the cache, we had best also set a timeout that clears the cache and disposes the item, perhaps, after 30 seconds. Otherwise, in situations like that, we'll have memory leaks.

Okay then. So what happens if the component renders and mounts? Well, it may continue to render afterward, including after more than 30 seconds have passed, and the component will still need access to that data. So it really shouldn't be garbage collected. But lucky for us, if a component mounts, React will necessarily execute a cleanup function so we don't need to rely on a timeout to clean up the item, meaning that an item should not be cleaned up while a mounted component references it, but instead, when that component unmounts. Okay. So with these three principles, you can safely make side effects during render. I have a library, react-disposable-state, under the Isograph github repo, where I expose extremely generic APIs for making side effects during render, and so on. I hope you check it out. Thanks.

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

Vue.js London Live 2021Vue.js London Live 2021
34 min
Everything Beyond State Management in Stores with Pinia
Top Content
When we think about Vuex, Pinia, or stores in general we often think about state management and the Flux patterns but not only do stores not always follow the Flux pattern, there is so much more about stores that make them worth using! Plugins, Devtools, server-side rendering, TypeScript integrations... Let's dive into everything beyond state management with Pinia with practical examples about plugins and Devtools to get the most out of your stores.
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit Remote Edition 2020React Summit Remote Edition 2020
30 min
React Query: It’s Time to Break up with your "Global State”!
Top Content
An increasing amount of data in our React applications is coming from remote and asynchronous sources and, even worse, continues to masquerade as "global state". In this talk, you'll get the lowdown on why most of your "global state" isn't really state at all and how React Query can help you fetch, cache and manage your asynchronous data with a fraction of the effort and code that you're used to.
React Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
Jotai is a state management library. We have been developing it primarily for React, but it's conceptually not tied to React. It this talk, we will see how Jotai atoms work and learn about the mental model we should have. Atoms are framework-agnostic abstraction to represent states, and they are basically just functions. Understanding the atom abstraction will help designing and implementing states in your applications with Jotai
JSNation 2022JSNation 2022
27 min
Announcing Starbeam: Universal Reactivity
Starbeam is a library for building reactive data systems that integrate natively with UI frameworks such as React, Vue, Svelte or Ember. In this talk, Yehuda will announce Starbeam. He will cover the motivation for the library, and then get into the details of how Starbeam reactivity works, and most importantly, how you can use it to build reactive libraries today that will work natively in any UI framework. If you're really adventurous, he will also talk about how you could use Starbeam in an existing app using your framework of choice and talk about the benefits of using Starbeam as the state management system in your application.
React Summit 2023React Summit 2023
22 min
Thinking in React Query
Top Content
In this talk, I'll explain React Query from a different perspective. After having maintained React Query for over two years and having answered many questions (often the same ones multiple times), I feel like there might be a fundamental understanding missing about the lib. I'll start with a quick introduction about my journey into open source and how I got to know React Query, followed by showing which mindset change is beneficial when working with React Query - how to "think in React Query". I'll have 3 major takeaways: 1) React Query is not a data fetching library It's an async state manager, we'll quickly talk about what makes a state manager, why React Query is one and what "async state" means. 2) staleTime is your best friend I've seen a bit of confusion about how to use React Query as a state manager, so I'll explain why setting staleTime is mostly all you need 3) parameters are dependencies This is important to understand to show the boundaries between client state and server state, and is essential when doing state management with React Query I will then end with a note on "separation of concerns" and about the tradeoffs of just calling `useQuery` wherever you need it in your component tree.

Workshops on related topic

React Summit 2020React Summit 2020
96 min
Rethinking Server State with React Query
Top Content
Featured Workshop
The distinction between server state and client state in our applications might be a new concept for some, but it is very important to understand when delivering a top-notch user experience. Server state comes with unique problems that often sneak into our applications surprise like:
- Sharing Data across apps- Caching & Persistence- Deduping Requests- Background Updates- Managing “Stale” Data- Pagination & Incremental fetching- Memory & Garbage Collection- Optimistic Updates
Traditional “Global State” managers pretend these challenges don’t exist and this ultimately results in developers building their own on-the-fly attempts to mitigate them.
In this workshop, we will build an application that exposes these issues, allows us to understand them better, and finally turn them from challenges into features using a library designed for managing server-state called React Query.
By the end of the workshop, you will have a better understanding of server state, client state, syncing asynchronous data (mouthful, I know), and React Query.
React Summit Remote Edition 2021React Summit Remote Edition 2021
71 min
State Management in React with Context and Hooks
WorkshopFree
A lot has changed in the world of state management in React the last few years. Where Redux used to be the main library for this, the introduction of the React Context and Hook APIs has shaken things up. No longer do you need external libraries to handle both component and global state in your applications. In this workshop you'll learn the different approaches to state management in the post-Redux era of React, all based on Hooks! And as a bonus, we'll explore two upcoming state management libraries in the React ecosystem.