React Query: It’s Time to Break up with your "Global State”!

Rate this content
Bookmark

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.

This talk has been presented at React Summit Remote Edition 2020, check out the latest edition of this React Conference.

FAQ

Tanner Linsley is a co-founder and VP of UI and UX at nozzle.io, where he builds SEO rank tracking software for enterprises. He is passionate about React and JavaScript and enjoys building open-source software.

Challenges associated with server state include caching, deduping requests, updating data in the background, dealing with outdated requests, mutations, pagination, incremental fetching, garbage collection, and error memory management. Many global state patterns do not offer solutions for these challenges.

React Query is an NPM library that provides hooks and utilities to solve asynchronous server state management in React applications. It aims to help both novice and advanced React developers with a simple and small API that requires little to zero configuration.

React Query improves performance by handling caching and background refetching out of the box. This allows for immediate rendering of cached data and smooth updates, enhancing the overall user experience by reducing loading states and making the application feel faster.

React Query is not necessarily a replacement for Redux. While it can handle server state effectively, many developers still use Redux for managing true client-side application state. Both can coexist and complement each other in a React application.

React Query handles mutations using the useMutation hook, which simplifies the code by managing mutation state and providing options like onSuccess and onError callbacks. These callbacks help in refetching related queries and handling side effects declaratively.

Optimistic updates in React Query allow the UI to immediately reflect what is expected to be the future state after a server mutation, providing a smoother user experience. If the mutation fails, the UI can roll back to the previous state.

Yes, React Query can support GraphQL. While it does not use Apollo Client, it can work with any simple GraphQL client that returns a promise and data.

Global state management refers to the practice of managing and accessing state (data) across different parts of an application without the need for prop drilling. It allows for data sharing between isolated components and hooks, making it more accessible and reducing code duplication.

Client state is temporary, local, and generally not persisted between sessions. It is accessed with synchronous APIs and is owned by the client's application instance. Server state, on the other hand, is persisted remotely, accessed with asynchronous APIs, and has shared ownership, meaning it can be manipulated by both the server and other clients.

Tanner Linsley
Tanner Linsley
30 min
02 Aug, 2021

Comments

Sign in or register to post your comment.
Video Summary and Transcription
In this video, the speaker discusses the common mistake of using global state for server state and introduces React Query as a solution. React Query simplifies managing server state by handling caching, background refetching, and optimistic updates, which enhance the user experience. The speaker demonstrates these features using a blog application built with React and Next.js. They explain how moving fetching logic to a root component can prevent duplicate requests and improve performance. React Query's useMutation hook is highlighted for handling side effects and making UI updates faster. The video also mentions how React Query can work with GraphQL clients and can be combined with other state management solutions like Redux. Finally, the speaker compares React Query to SWR, noting its superior flexibility in caching and handling mutations.

1. Introduction to Global State Management

Short description:

Hi, I'm Tanner Linsley, co-founder and VP of UI and UX at nozzle.io. Today, I want to talk about global state management and the mistake of placing server state in global state. Server state is different from client state in terms of storage, access speed, and ownership. Let's explore why and how we can handle server state more effectively.

Hi everyone. My name is Tanner Linsley, and I'm a co-founder and VP of UI and UX at nozzle.io, where we build SEO rank tracking software for enterprise. I absolutely love React and JavaScript, and I have a bit of an obsession for building open source software as well.

So since learning React, I've been super obsessed with topics like static site generation, data visualization, and animation. But today I'd like to talk to you about what is possibly my favorite one of all, global state management.

Today, a ton of code in our applications is dedicated to consuming and manipulating asynchronous data. Whether that data comes from our users or servers or third party APIs, it's absolutely critical for our apps to provide value to our users. In fact, for a lot of us, our applications are just opinionated user interfaces for consuming and managing this data.

Over the years, I've noticed that patterns around accessing and manipulating our data in our applications have quickly taken up residence with what we all know as global state. Global state is super convenient. It helps us avoid prop drilling, and it lets us access data across our application without copying or duplicating it. And it even helps us communicate between isolated components and hooks that otherwise wouldn't be able to. In the end, it just helps us do more with less code. It's extremely accessible and powerful, so it's only natural that we would want all of our important server side data to be just as accessible as our global state. And with that expectation, it's no surprise that we as React developers have chosen to co-locate our server side data with the rest of our global state.

It's relatively easy to do this by using something like local component state with React context, or even by using any number of libraries from the ever-growing list of global state management tools out there. But in the end, the expectation is usually the same. We expect our global state not only to be able to handle trivial things like menu state, themes, things like toasts and alerts, but we also expect it to be responsible for complex life cycles around fetching and providing our server side and asynchronous data to our users.

So today, I'm here to tell you that despite the fleeting convenience global state gives us when working with server side data, I think we've made a really big mistake by placing it there. We've tricked ourselves and our code into thinking that all state is created equal, when I think our asynchronous data and global state could not be more different, especially when it comes to where they're stored, the speed at which we access them, and how we access and update them, and ultimately who can make changes to them.

To make all this easier to understand, I want to stop using the term global state and instead call these two different types of state client state and server state. Client state is relatively simple and should be familiar to most developers. It's temporary and local, and it's generally not persisted between sessions. It's accessed with synchronous APIs that don't have any latency, and most of it is owned by our client's application instance. So for all those reasons, we can pretty much rely on our client state always being up to date at any given time in our application.

Server state, however, is pretty different. Server state is persisted remotely, so the location source of truth for our server state is potentially unknown, or at least outside of our control. It's asynchronous, so we have to access it with asynchronous APIs, and it also has implied shared ownership, which means that it's not just owned by our client. It can be read and manipulated by both the server and any other potential clients that interact with it. Because of all these things, very few guarantees can actually be made around our server state always being up to date in our apps, and instead we usually end up relying on just snapshots of our async data.

2. Server State and Client State

Short description:

When server state and client state are stored in the same system, tradeoffs are made. Server state has unique challenges that require dedicated tools. React Query is an NPM library that solves asynchronous server state with a small, simple API. To demonstrate its capabilities, I built a blog application with React and Next.js. The app allows viewing, editing, and adding posts. Initially, the app had four main components, each using useEffect and React State for data fetching and loading states. However, I wanted to make the code more portable.

So when we take these two very different types of state, server state and client state, and try and store them in the same system, we'll eventually make tradeoffs that favor one or the other. A good example of this is that server state has its own unique challenges that we never face with client state. For example, a few of these might be things like caching, deduping requests, updating data in the background, dealing with outdated requests, dealing with mutations, pagination and incremental fetching, or even garbage collection, error memory management, and everything else that comes with caching in general. Many global state patterns don't offer solutions for these kinds of challenges, or at the very least attempt to solve them with complicated APIs or overengineered plugin systems, and sometimes even overpowered APIs that are basically foot guns for the average React developer.

Server state and client state clearly both need plenty of love, but they each need it in their own way. And while I think they have a few things in common when it comes to how we access them in our apps, I think it's time for server state and client state to break up. There is way more to server state than just being globally accessible, and I think it deserves new dedicated tools that not only solve these challenges, but automatically handle them in an elegant way. This is exactly why I decided to build React Query. React Query is an NPM library comprised of a couple hooks and utilities that aim to solve asynchronous server state. It's a small API, it's simple, and it's designed to help both novice and advanced React developers be successful while requiring little to zero configuration.

To really know how React Query can drastically transform the way you handle server state, I decided to build a small interactive blog application using React and a little API powered by Next.js. So the purpose of this application is pretty simple. It's to show a list of posts, it lets us look at a detailed view of an individual post, and then it allows us to edit existing posts or add new ones as well. I'm going to navigate through a few stages or commits that I made to this project of how this application's state management evolved in the wild and how, in the end, I finally got to use React Query to save the day.

So first, let's just get familiar with the app. We have a trusty sidebar with a single link into our post page. We have a post page that fetches all of our posts from our API and displays them in a list. We can click on a post and load the detailed view with the full content. We can use the edit form at the bottom to edit the post. And then back on our post list, we can use that same form to add a new post to the list. So to do all of this, our app started out with four main components. An app component, which handles all of our routing and routing state. A post component, which fetches our posts from the API and then displays them with the add new post form underneath them. An individual post component that fetches the full content for a post and renders it and then gives us the edit form at the bottom. And then finally, we have a reusable post form component that just is for editing the post fields. So in each of these post components, right now we're just using a use effect strategy to call an asynchronous function and fetch our data. And then we use React State to keep track of the loading states for those requests. This way, when we mount each of those components, the data gets requested and eventually gets rendered in our UI. And all of this is fine and it works, but I personally don't like having a lot of business logic in my components. So I want to see if we can make this a bit more portable.

QnA

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 API Design – Lessons Learned
React Advanced 2024React Advanced 2024
26 min
React Query API Design – Lessons Learned
Top Content
I'm super excited to be here today, giving my first live talk at an in-person conference. Dominik, the maintainer of React Query, walks through the API design decisions, including success stories, trade-offs, and mistakes. Tener Linsley designed React Query's medium-sized query API to be minimal, intuitive, powerful, and flexible. Major versions in open source require marketing efforts, but not primarily for adding new features. TypeScript is crucial for building projects and managing user demands in open source can be challenging. The addition of the max pages option improved performance and avoided unnecessary refetches. Inversion of control gives users flexibility, but mistakes can happen in API design. Open source requires time management and feedback from users. API design is influenced by typing ease and good TypeScript support. Getting involved in open source involves trial and error and joining community platforms like TanStack Discord. Dominik's journey started during the pandemic and he can be found on Twitter, TanStack Discord, and his blog.
Managing React State: 10 Years of Lessons Learned
React Day Berlin 2023React Day Berlin 2023
16 min
Managing React State: 10 Years of Lessons Learned
Top Content
Watch video: Managing React State: 10 Years of Lessons Learned
This Talk focuses on effective React state management and lessons learned over the past 10 years. Key points include separating related state, utilizing UseReducer for protecting state and updating multiple pieces of state simultaneously, avoiding unnecessary state syncing with useEffect, using abstractions like React Query or SWR for fetching data, simplifying state management with custom hooks, and leveraging refs and third-party libraries for managing state. Additional resources and services are also provided for further learning and support.
SolidJS: Why All the Suspense?
JSNation 2023JSNation 2023
28 min
SolidJS: Why All the Suspense?
Top Content
Suspense is a mechanism for orchestrating asynchronous state changes in JavaScript frameworks. It ensures async consistency in UIs and helps avoid trust erosion and inconsistencies. Suspense boundaries are used to hoist data fetching and create consistency zones based on the user interface. They can handle loading states of multiple resources and control state loading in applications. Suspense can be used for transitions, providing a smoother user experience and allowing prioritization of important content.
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.

Workshops on related topic

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.
Fetch, useEffect, React Query, SWR, what else?
React Advanced 2023React Advanced 2023
102 min
Fetch, useEffect, React Query, SWR, what else?
Top Content
WorkshopFree
Ondrej Polesny
Ondrej Polesny
In this workshop, first, we’ll go over the different ways you can consume APIs in React. Then, we’ll test each one by fetching content from a headless CMS (with both REST and GraphQL) and checking in detail how they work.
While there is no advanced React knowledge required, this is going to be a hands-on session, so you’ll need to clone a preconfigured GitHub repository and utilize your preferred React programming editor, like VS Code.
You will learn:- What diverse data fetching options there are in React- What are advantages and disadvantages of each- What are the typical use cases and when each strategy is more beneficial than others
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
React Summit 2023React Summit 2023
139 min
Create a Visually Editable Next.js Website Using React Bricks, With Blog and E-commerce
Top Content
WorkshopFree
Matteo Frana
Matteo Frana
- React Bricks: why we built it, what it is and how it works- Create a free account- Create a new project with Next.js and Tailwind- Explore the directory structure- Anatomy of a Brick- Create a new Brick (Text-Image)- Add a title and description with RichText visual editing- Add an Image with visual editing- Add Sidebar controls to edit props (padding and image side)- Nesting Bricks using the Repeater component- Create an Image gallery brick- Publish on Netlify or Vercel- Page Types and Custom fields- Access Page meta values- Internationalization- How to reuse content across pages: Stories and Embeds- How to create an E-commerce with Products’ data from an external database and landing pages created visually in React Bricks- Advanced enterprise features: flexible permissions, locked structure, custom visual components
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.