Suspense for Data Fetching: How to Fetch During Render

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!

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

Watch video on a separate page

FAQ

Fetching data in advance can be better because it allows the relevant content to be shown to the user even sooner, as the network request is made before the initial render.

Fetching during render might be the best option in situations where it's difficult to determine an appropriate moment to start the network request, such as when a modal is shown based on some opaque function of a complex state.

In the context of fetching data, a side effect is an operation that should be performed only once and must be cleaned up afterwards, such as making a network request and managing the received data.

Fetched data should be garbage collected if the UI no longer needs it to avoid running out of memory on low-end devices. Data should also be removed from the cache after a certain period, like 30 seconds, to ensure that new network requests are made as needed.

No, API calls cannot be made directly within the render function in React because the render function may execute multiple times, and we need to reuse the previous network request rather than making a new one each time.

Hooks cannot be used to store information about the API call because if a component renders, suspends, and renders a second time, all hooks will be created anew for the second render, losing the information about the previous API call.

The information about the network request should be stored in something that outlives the render function, such as props, context, or a global object.

The principles for safely making side effects during render include using an external cache, setting a timeout to clear the cache and dispose of the item to avoid memory leaks, and ensuring that an item is not cleaned up while a mounted component references it.

The 'react-disposable-state' library provides extremely generic APIs for making side effects during render, allowing developers to manage side effects and cleanup in a React component effectively.

Fetching data during the initial render is important because it allows us to show the user what they want to see as soon as possible, improving the user experience.

Robert Balicki
Robert Balicki
5 min
15 Nov, 2023

Comments

Sign in or register to post your comment.
  • Robert Balicki
    Robert Balicki
    Ah, sorry about the confusion! See https://github.com/isographlabs/isograph/tree/main/libs/isograph-react-disposable-state for the URL of the repo. @isograph/react-disposable-state is the name on npm! You can find that here: https://www.npmjs.com/package/@isograph/react-disposable-state
  • Developer
    Developer
    -
    The repo @isograph/react-disposable-state doesn't exist.
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.

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

Everything Beyond State Management in Stores with Pinia
Vue.js London Live 2021Vue.js London Live 2021
34 min
Everything Beyond State Management in Stores with Pinia
Top Content
State management is not limited to complex applications and transitioning to a store offers significant benefits. Pinia is a centralized state management solution compatible with Vue 2 and Vue 3, providing advanced devtools support and extensibility with plugins. The core API of Pinia is similar to Vuex, but with a less verbose version of stores and powerful plugins. Pinia allows for easy state inspection, error handling, and testing. It is recommended to create one file per store for better organization and Pinia offers a more efficient performance compared to V-rex.
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.
React Query: It’s Time to Break up with your "Global State”!
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
Global state management and the challenges of placing server state in global state are discussed. React Query is introduced as a solution for handling asynchronous server state. The Talk demonstrates the process of extracting logic into custom hooks and fixing issues with state and fetching logic. Optimistic updates with mutation are showcased, along with the benefits of using React Query for data fetching and mutations. The future of global state management is discussed, along with user feedback on React Query. The Talk concludes with an invitation to explore React Query for server state management.
Jotai Atoms Are Just Functions
React Day Berlin 2022React Day Berlin 2022
22 min
Jotai Atoms Are Just Functions
Top Content
State management in React is a highly discussed topic with many libraries and solutions. Jotai is a new library based on atoms, which represent pieces of state. Atoms in Jotai are used to define state without holding values and can be used for global, semi-global, or local states. Jotai atoms are reusable definitions that are independent from React and can be used without React in an experimental library called Jotajsx.
Announcing Starbeam: Universal Reactivity
JSNation 2022JSNation 2022
27 min
Announcing Starbeam: Universal Reactivity
Starbeam is a library for building reactive user interfaces with JavaScript, similar to Svelte, Vue, and Ember. It provides a data structure and query feature for filtering and sorting. The useStarBeam function ensures JSX reconciliation only occurs when reactive dependencies change. Starbeam tracks every read and write operation to update the component accordingly. It can be used with React and other frameworks, and offers debugging tools and locale integration.
Thinking in React Query
React Summit 2023React Summit 2023
22 min
Thinking in React Query
Top Content
Watch video: Thinking in React Query
React Query is not a data fetching library, but an Asian state manager. It helps keep data up to date and manage agent life cycles efficiently. React Query provides fine-grained subscriptions and allows for adjusting stale time to control data fetching behavior. Defining stale time and managing dependencies are important aspects of working with React Query. Using the URL as a state manager and Zustand for managing filters in React Query can be powerful.

Workshops on related topic

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.
Rethinking Server State with React Query
React Summit 2020React Summit 2020
96 min
Rethinking Server State with React Query
Top Content
Featured Workshop
Tanner Linsley
Tanner Linsley
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.
Getting Started with Suspense and Concurrent Rendering in React
React Summit 2020React Summit 2020
125 min
Getting Started with Suspense and Concurrent Rendering in React
Featured Workshop
Maurice de Beijer
Maurice de Beijer
React keeps on evolving and making hard things easier for the average developer.
One case, where React was not particularly hard but very repetitive, is working with AJAX request. There is always the trinity of loading, success and possible error states that had to be handled each time. But no more as the `<Suspense />` component makes life much easier.
Another case is performance of larger and complex applications. Usually React is fast enough but with a large application rendering components can conflict with user interactions. Concurrent rendering will, mostly automatically, take care of this.
You will learn all about using <Suspense />, showing loading indicators and handling errors. You will see how easy it is to get started with concurrent rendering. You will make suspense even more capable combining it with concurrent rendering, the `useTransition()` hook and the <SuspenseList /> component.
State Management in React with Context and Hooks
React Summit Remote Edition 2021React Summit Remote Edition 2021
71 min
State Management in React with Context and Hooks
WorkshopFree
Roy Derks
Roy Derks
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.