Stop Abusing Client State Management

This ad is not shown to multipass and full ticket holders
React Summit US
React Summit US 2025
November 18 - 21, 2025
New York, US & Online
The biggest React conference in the US
Learn More
In partnership with Focus Reactive
Upcoming event
React Summit US 2025
React Summit US 2025
November 18 - 21, 2025. New York, US & Online
Learn more
Bookmark
Rate this content

A lot of React applications out there run for state management solutions such as Redux or Mobx and use it mostly for server side state like 'isLoading', 'isError', etc. We need to stop mixing between server state and client state. Don't get me wrong, client state is important, but 70% of the state is actually a server state. In this talk I will demonstrate how we can encapsulate server state using our own custom hook or using a (perfect) solution such as react-query.

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

FAQ

Nir is a 34-year-old from Israel, married to a frat, and father to three daughters. He has built web apps since childhood and has a BSc in Computer Science from the Hebrew University of Jerusalem.

Nir's first web project was the Biggest Israeli Pokemon Fans website.

Nir holds a BSc in Computer Science from the Hebrew University of Jerusalem.

Nir has worked as a full-stack developer at Intel, a frontend team leader at Curv (a blockchain startup acquired by PayPal), and currently runs a consulting company in webapps development.

Nir's consulting company focuses on webapps development in both web 2.0 and web 3.0.

Nir discusses state management tools like Redux, MobX, and React Query.

The custom hook 'useAsync' is created to handle async functions, manage loading, success, and error states, and provide caching and retry mechanisms.

React Query is a library that handles API functionality such as fetching, caching, loading, and retry mechanisms, simplifying server state management in React applications.

Nir recommends React Query because it simplifies handling API functionality, including caching, retry mechanisms, and invalidation, making it very helpful for every React application.

Server state involves handling API functionality like fetching and caching, while client state involves UI elements like dialog boxes and menu bars. Nir suggests using tools like React Query for server state and Redux or MobX for client state.

Nir Parisian
Nir Parisian
21 min
21 Jun, 2022

Comments

Sign in or register to post your comment.
Video Summary and Transcription
This Talk discusses state management abuse and the use of React Query for API handling in React applications. The speaker demonstrates implementing loading indicators, custom hooks, caching mechanisms, and introduces React Query as a powerful tool for fetching, caching, and loading data. The conclusion emphasizes that React Query simplifies API handling without the need for complex state management tools like Redux or MobX.

1. Introduction

Short description:

Hi everyone. My name is Nir. I'm 34 years old from Israel, married to a frat and father to three little wonderful girls. I've built web apps since I was a kid. Currently I run a consulting company in webapps development, both in the world of web 2.0 and web 3.0.

Hi everyone. My name is Nir. I'm 34 years old from Israel, married to a frat and father to three little wonderful girls, Baar and Adas. I've built web apps since I was a kid. My first website was the Biggest Israeli Pokemon Fans website and it was a great project. Since then I had my BSc in Computer Science at the Hebrew University of Jerusalem. I worked as a full-stack at Intel for a couple of years. Afterwards I was a frontend team leader at Curv, a blockchain startup which acquired by PayPal. Currently I run a consulting company in webapps development, both in the world of web 2.0 which you're all familiar with, and also in the web 3.0 world.

Read also

2. State Management Common Abuse

Short description:

Let's talk about state management common abuse. We choose our favorite state management tool, connect components to backend API functionality, and start using state management awesomeness. I created a React application, declared an API function called fetchPokemon, and used a Pokemon API service to fetch relevant data. I added a two-second delay, fetched the data, and implemented the UI to display the Pokemon data and a button to fetch random Pokemon. Finally, I added some styling to the UI.

Enough about me, let's talk about state management common abuse. So we've all been there, starting a React application, choosing our favorite state management tool, like Redux or Morbix, or many others out there, and connecting our components using these tools to our backend API functionality and start using state management awesomeness.

Let's see it in action. I created a simple React application using code sandbox, and I'll start by declaring an API function called fetchPokemon, which will get in the parameters the Pokemon name, and we will use a Pokemon API service to fetch the relevant Pokemon data. I wrapped it with a promise to make sure we get some delay in the response to mock a common behavior of API functions. So there's a setTimeout, and I set it later to two seconds of delay.

Now I'll do the fetching. We have the Pokemon name, handle the response, which is in a JSON format, so I'll use the JSON, and return the data. Cool. Great. Let's add the two seconds delay I talked about, and now I can call the endpoint in the UI, declaring the state PokemonData and setPokemonData using the useState hook, and creating a fetch random Pokemon function so the app won't be boring.

So I'll be using or I'll be choosing out of three common Pokemons, Pikachu, Charizard, and Squirtle. We will use some random logic using the math library, so multiplying math random with the array length minus 1 and round it up. And now I can use it. I'm calling the fetchPokemon with the chosen Pokemon name. Cool. Return the data. Great. And now for the best part, the UI. So I will declare a div container and display the Pokemon data in a div and create a button for using the fetch function. So in the div, I will display the Pokemon name as well as its image using the sprites data which we get from the Service API. Put it in the image source. And great! Back to the button. I will attach the fetch random Pokemon, which we implemented. And let's add some text. And let's add some alternative text to remove the annoying warning of the Kot Sandbox. Add some typo here. And test it. Cool! We've got Squidward. Now let's add some style, just to move the text a little bit up above.

3. Implementing Loading Indicator

Short description:

And we are done! We've got Toysard, and Squirtle, and Pikachu. I will use user reducer for simplicity reasons. Let's add a state for error data and a success state. Let's adapt the UI to use our new state variable. Implement the loading indicator easily. Fix the bug in the SetTimeout.

And we are done! We've got Toysard, and Squirtle, and Pikachu. Great! I think to myself, an app is not an app without some loading indicator. That's the part where most developers will use Redux or some other solution to hold these kind of states.

I will use user reducer for simplicity reasons, which is very similar to Redux reducers. So I'll create a Pokemon Reducer, getting a state and an action, and switching the action type. So first let's handle a default case, throw in some error, and now add the common loading state. Status is loading, and great. But what if I get an error? So let's add a state for this as well, with the error data, and surely we need a success state to hold the data getting from the Service API. And since we can be sometimes not in neither of these states, let's add an idle state and declare an initial state to begin with.

Now I can just use it in the application, instead of the regular useState. So extracting the state and the dispatch function out of the reducer, using the PokémonReducer and the initial state. And let's adapt the UI to use our new state variable. So when I'm idle, I will display some text, click to fetch a Pokémon, and on success I want to display the Pokémon data. So let's implement this as well. Pay attention that Pokémon data doesn't exist anymore, so we'll replace it with the state variable. And on error, I want to display the error message, which I saved in the state. And finally, I want to disable the button while I'm on loading state.

Now I can finally implement the loading indicator easily. So what I will do, I will switch the button text to loading when I'm in the status of loading. And display the FetchPokemon text when I'm not. Fetching. Okay, and don't forget to dispatch the right state when loading. And when receiving the data. With the data. And when encountering some error. Let's hit the refresh and test it. And I see we don't get the loading indicator. So I think I know why we have some bug in the SetTimeout. Let's fix that. Great.

4. Implementing Custom Hook

Short description:

Test again and we got this. Just the style. We missed the style. So let's move the style to the inner div we implemented. Usually for this kind of async function, developers write different reducers, but I know a better way to share some logic. Custom hooks. Let's create one. Let's take the reducer, move it down and declare a custom hook named userSync. And now let's create a function called execute that will be responsible for changing the state using the dispatch.

Test again and we got this. Just the style. We missed the style. So let's move the style to the inner div we implemented. And great. Test again. Cool.

Usually for this kind of async function, developers write different reducers, but I know a better way to share some logic. Custom hooks. So let's create one. So let's take the reducer, move it down and declare a custom hook which I will name userSync. Okay. The userSync will get an async function. And actually, we can use our reducer. Let's just rename it to something more generic. So fetchReducer might be better. And we can use it in our hook. Great.

And now let's create a function that will be responsible to changing the state using the dispatch. So we'll name it execute. And this function will get parameters of course. And start by dispatching the loading state. Then we will call the async function argument we got with the params. And onSuccess, dispatch the success state. We have the data, of course. And last but not least, when getting an error, we will dispatch the error state, similar to what we did earlier. Quit error with the error data. Now I will have the execute function with use callback to avoid re-renders, except the time, of course, when the function does change. And finally we return from the hook the execute function and the state, which we can use in the application. And let's actually use it.

5. Extracting Execute and State

Short description:

Let's extract execute and state out of the user sync custom hook and pass it our function, fetchRandomPokemon. This pattern is not my invention but rather something I found in a library called user sync, which is implemented very similarly to what we did. It's an amazing library with many other custom hooks.

So let's extract execute and state out of the user sync custom hook, and we need to pass it our function, so fetchRandomPokemon. And let's make some adjustment. We move in the dispatch and move in this function out of the application. Call in execute. Great. And this is working nice. So actually I didn't invent any of that. I just use a pattern I met in the school library, use hooks, and you can see here user sync, which is implemented very similar to what we did. And it's actually amazing and this library has many other custom hooks. I really suggest checking it out.

6. Implementing Cache Mechanism

Short description:

Let's add a cache mechanism to store the fetched data and implement caching. If the data exists in the cache, it will be returned. Otherwise, it will be fetched using an async function and saved in the cache. We can also add invalidation to reset the cache when the data is not up to date. This allows us to re-fetch the data when necessary, such as when a timer is connected.

So with your permission and to make some point, I'm getting rid of the Pokemon randomness for a while and fetching only the great Pikachu. Notice that I am fetching the data every time I click, even though I have the same data all the time. Pikachu. So I think it will be nice to add some cache mechanism. I'll add a cache variable which will hold the data and add some flag named with cache and let's call it with true. And let's implement the caching. So if the data does exist, I will return it from the cache. Right, if it exists. And otherwise, I will fetch it using the async function and save it in the cache. Great. Let's test it. Now it's fetching, and for the second time and third time and so on, it won't fetch again because it's using the cached data. And let's add some invalidation to make sure we support when the data is not up to date. So if invalidate flag is true, I'm resetting the cache. Let's add it to the dependencies array. And now let's set the flag to true. And if I click over and over again, I'm fetching. This is good when I want to tell my custom hook that the data is not relevant anymore and I want to re-fetch it. So I can connect a timer to it or something like that.

7. Introducing React Query

Short description:

React Query is my first choice for dealing with API LL. It provides a built-in hook called Use Query that includes everything we implemented in UserSync. We can replace UserSync with Use Query, passing the Query key and query function as parameters. The result includes data, error indicators, and a refresh function. With React Query, we get caching out of the box.

And you know what? It's so cool to add some retry mechanism. And I think you know where I'm going with it. We don't have to work this hard, although it is fun. So I want you to meet React Query, which is my first choice when dealing with the API LL.

So first I'll wrap it up real quick with the React Query provider. Coming from the React Query library, which I just installed. And wrapping the entire application with the provider and the client. And now I can use the built-in hook from React Query called Use Query. So this hook actually holds everything we just implemented in UserSync, including the cache system, the retry mechanism, the invalidation, and many other cool functionalities.

We can get rid of the UserSync and let's use Use Query instead. It has two parameters, actually. The first one is the Query key, which serves as the id of the query. And the second one is the query function, as similar as the UserSync hook we just implemented. So, this will be the FetchPokemon function, currently with Pikachu. And let's extract everything out of the result. So we have the data. We have some indicators, like if there was an error, if it's loading, and so on. And let's use it in the UI, make some adjustments. Great, the error. We can remove this and use the IsError flag, which we got for free. And the error variable, which we can extract as well. And the refresh function, which will replace the execute from the user's sync hook. Great, isLoading here instead. And here as well. Not IsLoading. Cool. And great, we got the caching out of the box. Let's clear things out. All of this. Oh, this is such a good feeling.

8. Conclusion and Recommendation

Short description:

And we can even use the fetch random Pokemon once again and get in the cache. So here is the React Query library website. It has some cool documentation and functionality that makes handling the API layer simple. In conclusion, we connected a simple API function to a simple UI. As the UI grows, handling API functionality becomes more complicated. We don't need fancy tools like Redux or MobX for server state handling. React Query is a helpful solution for fetching, caching, and loading in every React application.

And we can even use the fetch random Pokemon once again and get in the cache. Great. Everything works.

So here is the React Query library website. Which is very great. It has some cool documentation. And I really suggest going over it. It has so much functionality which is useful. And really makes things very simple relating to handling the API layer. So it's really worth checking.

So in conclusion, what we did here was taking a simple API function and connecting it to a really simple UI. But as you can imagine, as the UI gets bigger and bigger, it gets more and more complicated to handle this kind of API functionality. And we don't need fancy tools such as Redux, MobX or many others out there to handle what is called server states. These tools are meant for client state operations such as if the dialog is open, if a menu bar is open, if I'm logged in or not logged in. This is client state. In any case of server state handling, such as fetching, caching, loading and so on, I really suggest either build some similar solution to use query or use async, custom hooks we just saw or really consider using React query which is really, really helpful in actually every application, every React application I saw so far. So hope you had a great time.

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.
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.
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.

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
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
Workshop
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.