React Query for Simpler State Management

36012-react_query_for_simpler_state_management.jpg

Hi, my name is Kostiantyn. With over 10 years of experience in developing single-page applications, I've always found Redux state management to be overly complex. However, while working on large Angular projects where state is stored in services, I realized that Redux could be quite suitable. Managing state with numerous RxJs Subjects scattered throughout the application often leads to "spaghetti code," making the logic hard to follow. Although Redux and Redux Thunks seem complicated, they were the best options available until server state libraries like TanStack (React) Query emerged.

The Props Drilling Problem

Let’s give an overview of a modern approach to state management in React applications. 

When you learn the React framework, the first state management approach you use is setState(useState). Your component starts to have its state, but it gets bigger, and you need to reuse the state with children's components. The state gets passed as props. And if we need to reuse state in the components without direct child-parent connection, we end up having what is called “Props drilling”:

How to Solve the Prop Drilling Issue

As you can see, every component in the tree has props that it does not need. The purpose of the “message” prop is only to pass it down the tree. This creates a close coupling of overcomplicated component interfaces with mixed own and passing-down props. Another issue with this approach is that as our application grows, we need a central place to store all our application data to debug it easily.

Here, we use Context + useReducer to store the application state. Thus, we solved the issue with props draining, and also, our application state is stored in the context, it is global, and it can be easily debugged in developer tools. If our application has many values in the context state and our component is only concerned with some part of it, it will still be re-rendered on each context value change. So if our context storage grows, we need to split it so that each application part depends on the needed context slice. Maybe we also need some tools for historical updates.

Redux helps you manage a "global" state that is needed across many parts of your application. In most projects I have worked on, the “global” state comes from the back-end. So Redux suggests saving the global state to store, and the local component state can be saved inside the component’s local React State. 

What is React Query?

There is another library called React Query, which creators argue that we should not keep a state that does not belong to the front end, in-store calling such a state “Server state” which means that it belongs to the server and the server database is a single source of truth for it. So they approached this using a stale-while-revalidate caching mechanism. Let’s say our grandpa’s message comes from the back-end:

What we see in the console:

Console

Only one request, meaning React Query, stores our grandpa’s message and propagates it through our tree of components. It will also re-fetch data and update the cache when it is stale. It happens on timeout or window focus, which can be adjusted in settings. Since most front-end applications state is “owned by server” it is wise to store server state in the same place where it got fetched. 

This way appears to have the least boilerplate, as we have a state manager and caching library. 

Web Development Services and Solutions Require the Most Reliable Partners Explore how Svitla Systems can guide your web development journey with expertise and innovative solutions. Contact Us

React Query Integrations

Official React Query documentation says that for large client states, you can still use state libraries like Redux or Zustand:

Redux or Zustand

Redux has its caching library RTK Query, so it is more sensible to use Zustand as a state manager for the React Query application because it is small and simple. In the following example, we store key query in the Zustand store manager. In turn, to switch between React queries dynamically, we take queryKey from the Zustand store. 

React Query Drawbacks

What are the drawbacks of using React Query? The main is library size:

LibrarySize (minified)
Zustand3.1 Kb
Redux3.7 Kb
SWR15 Kb
Mobx15.7 Kb
React Query57.2 Kb

React Query is a feature that goes for the cost of increased bundle size. In case you are developing a desktop application, it is not a problem, but it may be a reason to choose a different library for a mobile app, where a small bundle size is essential.

Summary

Based on my experience, Redux is still a very popular approach to state management, especially considering that the React Toolkit removed a lot of boilerplate code, but in my opinion, it is still quite complicated. With the appearance of server state libraries like React Query, the usage of such Flux libraries was significantly narrowed. 

Nowadays, the time of developers is the most expensive part of application development, so businesses can use simple free tools like React Query without needing a complicated boilerplate to start an application, and later (if needed) they add Redux or other store libraries. All this makes it faster and cheaper to bootstrap your project, a newly hired developer can easily get on board, and the application starts to have less code and, thus, fewer bugs. Also, the store scheme becomes simpler as React Query stores server code.

So, for small apps and startups where project requirements are unclear and frequently change, I would start front-end development using React Query. 

FAQ

What is React Query?

React Query is a powerful server-state management library in React that can perform fetching and caching, plus synchronization and updates of data coming from APIs. Rather than persisting server data within any global state manager such as Redux, React Query operates with the backend as the single source of truth and efficiently manages this “server state,” using its stale-while-revalidate caching mechanism. Automatically refetching and updating the data when it becomes stale or whenever the browser regains focus on your application minimizes so much boilerplate while making reasoning about state logic super simple, Faster to develop applications that are easier to maintain with fewer bugs when your project is heavily dependent on backend data.

Is React Query enough for state management?

React Query is great at handling server state (that is, data fetched and synced with a backend), but it doesn’t totally eliminate the need for traditional state management tools. It manages caching, re-fetching, and syncs well, so you don’t need something as heavy as Redux most of the time. You still need React’s built-in state – or some tiny client-state library – to handle local UI things like modals, form inputs, or theme settings. In modern apps, React Query plus simple local state covers way more than enough.

When should I use React Query?

You should absolutely consider using React Query in your application if it’s quite server data-dependent and there’s a requirement for super-efficient fetching, caching, and synchronization of that data from the server. It makes a perfect fit for situations where the API is the place that generates the most state instead of the frontend. React Query handles refetching on its own when that data gets old or when the user returns to that window, which results in less manual code and fewer bugs. Perhaps this is of particular use for small-to-medium projects or startups in need of quick development, less boilerplate, and automatic handling of server data.

Is React Query replacing Redux?

React Query is not a full replacement for Redux. Both are complementary tools dedicated to the maintenance of the state, but used in various cases: React Query can manage server state effectively and conveniently, while Redux is more appropriate in cases when complex client-side or global UI state management is needed. In numerous contemporary applications, the use of React Query will contribute to the considerable minimization of the requirement of Redux, since it simplifies so much work concerning the server’s data. In case your application consists of significant client-side logic or requires a single central state apart from API data, then Redux or some other state library may be beneficial.

What is React Query and SWR?

React Query, SWR. Two libraries meant to simplify the fetch, cache, and sync server data exercise in a React application. These employ content update strategies whereby cached content is displayed while automatic background updating takes place; therefore, up-to-date information is always at hand. No manual data fetching logic or convoluted global stores are required. Cleaner and faster development process. React Query exposes much richer configuration possibilities. SWR only presents a reduced and simpler solution for small scenarios.