VOOZH about

URL: https://blog.logrocket.com/rtk-query-future-data-fetching-caching-redux/

⇱ RTK Query: The future of data fetching and caching for Redux - LogRocket Blog


2021-02-16
1615
#redux
Dylan Tientcheu
34405
👁 Image

See how LogRocket's Galileo AI surfaces the most severe issues for you

No signup required

Check it out

RTK Query is an experimental library from the Redux team with the main purpose of fetching and caching data for your web app. It utilizes Redux under the hood and is built on top of Redux Toolkit (RTK). RTK Query provides advanced setup options to handle your fetching and caching needs in the most flexible and efficient way possible.

👁 rtk-query-data-fetching

While RTK Query utilizes Redux under the hood, that doesn’t mean you need a sophisticated understanding of Redux to work with it. But learning both Redux and RTK will go a long way toward harnessing the state management capabilities RTK Query can provide for your web app.

🚀 Sign up for The Replay newsletter

The Replay is a weekly newsletter for dev and engineering leaders.

Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.

We don’t just write about Redux, we talk about it too. Listen now:

Or subscribe for later

Why would you use RTK Query ?

Today, RTK Query is still in its alpha stage, meaning it is subject to multiple breaking changes in its architecture and API. Nevertheless, it already delivers a simple and efficient solution for data caching and fetching.

RTK Query was built to address the need to fetch data when using Redux as your state management system. RTK Query can be added as a middleware and provides powerful React Hooks to help fetch your data. Despite its nascence, it’s safe to say that when RTK Query goes into production, it will be a perfect candidate to fetch data in JavaScript apps of all sizes.

In your typical small React app (without Redux), you’ll have the ability to fetch data with the integrated ApiProvider. On the other hand, in a bigger app (using Redux), you can still plug in RTK Query as a middleware in your store.

RTK Query’s agnosticism makes it easy to integrate with any framework capable of using Redux (Vue.js, Svelte, Angular, etc.). Note that while RTK Query is coined agnostic, it is also extremely opinionated, following Redux’s established paradigms. In addition, RTK Query is built with TypeScript, thus providing first-class types support.

Fetching and caching data with RTK Query

First things first: you need to set up your project to use RTK Query. We need to create a service definition that will fetch to our public API. For this example, we are using a Dungeons & Dragons API:

import { createApi, fetchBaseQuery } from "@rtk-incubator/rtk-query";

// Create your service using a base URL and expected endpoints
export const dndApi = createApi({
 reducerPath: "dndApi",
 baseQuery: fetchBaseQuery({ baseUrl: "https://www.dnd5eapi.co/api/" }),
 endpoints: (builder) => ({
 getMonstersByName: builder.query({
 query: (name: string) => `monsters/${name}`
 })
 })
});

export const { useGetMonstersByNameQuery } = dndApi;

As mentioned in the docs, RTK Query prefers centralizing its data fetching configuration, which is unlikely in different data fetching libraries — part of what makes it opinionated. Centralizing our setup has its pros and cons. For example, keeping our fetch hooks together is not a bad idea, but this could quickly grow cumbersome if working with an extensive API.

The next step is to add this service to our store by adding our generated reducer and our API middleware. This will turn on caching, prefetching, polling, and other RTK Query features.

export const store = configureStore({
 reducer: { [dndApi.reducerPath]: dndApi.reducer },
 middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(dndApi.middleware)
});

Next, you need to wrap the provider, as you’d do with a basic Redux store, then you can query in your components using your previously defined query hook.

import * as React from "react";
import { useGetMonstersByNameQuery } from "./services/dnd";
export default function App() {
// Using a query hook automatically fetches data and returns query values
const { data, error, isLoading } = useGetMonstersByNameQuery("aboleth");
return (
 <div className="App">
 {error ? (²²²²²²²²²
 <>Oh no, there was an error</>
 ) : isLoading ? (
 <>Loading...</>
 ) : data ? (
 <>
 <h3>{data.name}</h3>
 <h4> {data.speed.walk} </h4>
 </>
 ) : null}
 </div>
);
}

The complete application code is available in CodeSandbox.

Mutating data

Sometimes you need to create or update your data. RTK Query helps you do that in a standard way. The provided useMutation hook returns a tuple containing a trigger function and an object containing results from the trigger. In contrast to useQuery, the mutation is only performed when the trigger is called.

In a much more advanced setting, you may have a use case in which you need to synchronize your local cache with the server after you perform a mutation. This is called revalidation. RTK Query provides two scenarios to deal with this use case, and you can decide which to use based on your project needs:

  • Invalidating everything of a type
  • Selectively invalidating a list

While using RTK Query mutations, you’ll also have all the tools you need to implement optimistic update behavior: you can use the onStart phase of a mutation, where you manually set the cached data via updateQueryResult. In case an error occurs, you can use onError along with patchQueryResult to roll back to the previous state.

Where does caching comes into play?

Caching is automatic in RTK Query. If your data ever changes (i.e., is invalidated), refetching occurs automatically only for the elements that changed. This is handled via RTK Query’s powerful queryCachedKey.

Once a request is made, RTK Query will serialize the parameters to provide a unique queryCachedKey. This key is then verified in all future requests to prevent unnecessary refetching. If ever you need to go over this behavior, you can always call the refetch function that is provided by your hook.

Caching behavior is neatly illustrated in the docs along with a CodeSandbox example. This shows how the automated fetching and caching features help reduce the amount of requests.

Query statuses

It is also important to note how big a pain it can be to lift the states returned by the query. RTK Query exposes the request states, which can be directly used in our app, as shown in the example below:

isUninitialized: false; // Query has not started yet.
isLoading: false; // Query is currently loading for the first time. No data yet.
isFetching: false; // Query is currently fetching, but might have data from an earlier request.
isSuccess: false; // Query has data from a successful load.
isError: false; // Query is currently in "error" state.

Conditional fetching

As mentioned above, useQuery automatically fetches your data and handles the caching. RTK Query provides a way to stop a query from automatically running with a Boolean skip parameter that can be added to the query hook, which will help manage this behavior. Setting skip to false strongly affects the way your data is fetched and cached.

Error handling

Errors are returned through the error property provided by the hook. RTK Query expects you to return payloads (errors or successes) in a particular format to help with type inference.

return { error: { status: 500, data: { message: 'error reasons' } }; 

If you need to edit your current return format, you can use a custom baseQuery, which will help you mold your returned data.


Over 200k developers use LogRocket to create better digital experiences

👁 Image
Learn more →

To help you gracefully handle your errors, RTK Query exposes a retry utility with which you can wrap your baseQuery to create an exponential backoff of a specified number of attempts (maxRetries).

In addition, RTK Query also enables you to manage your errors at a macro level, which may help you log errors for unfulfilled async calls.

Polling

You can also get the feel of having a real-time server by using the exposed pollingInterval on your useQuery hooks. This parameter takes in a number in milliseconds, which will later be the interval at which your data refreshes. Moreover, you can also manually refresh your data.

Prefetching

Prefetching is simply fetching data before it is actually needed — for instance, if you need the next page of paginated data fetched before it is actually requested.

RTK Query handles this by enabling you to send in two arguments: isOlderThan and force. isOlderThan will run the query based on a Boolean or a timestamp, and force will ignore the isOlderThan argument and run the query even if it is present in the cache.

Code generator

Since it’s centralized, and RTK Query works with your hooks, it may quickly become cumbersome to write full API endpoints in your service file. To deal with that, RTK Query provides a CodeGen that works with OpenAPI schemas.

Customizability

It is crucial for every API client library to be fully customizable; a good example is Axios. This enables developers to have the capability to handle default behaviors, interceptors, and authentication without the need to repeat code.

createApi is the main point where RTK Query will be configured. It exposes parameters such as:

  • baseQuery, which could be customized to create interceptors or mold return formats
  • endpoints, which is the set of operations you perform against your servers
  • setupListeners, which is a utility to help manage refetching either in a global or granular way
  • Much more to handle your API calls and Redux store

Comparison with react-query

RTK Query resembles react-query in the way it utilizes hooks. However, the two libraries have slightly different approaches.

RTK Query focuses on harnessing Redux’s power to provide a much more efficient and declarative method to fetch data. It also aims to be agnostic by nature, with a tight dependency on Redux Toolkit.

Their caching strategies are quite different as well: RTK Query is declarative in data invalidation, and its cache key is created via endpoints and arguments, whereas react-query uses a manual cached key for invalidation and caches by user defined query keys.

RTK Query provides a more extensive comparison here.

Conclusion

When it reaches production, RTK Query will surely be a great addition to teams using Redux for their state management. Early signs show great promise — it already delivers a simple and efficient solution.

Get set up with LogRocket's modern error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID
  2. Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not server-side

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');
     
    // Add to your HTML:
    
    <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
     
  3. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • NgRx middleware
    • Vuex plugin
Get started now
👁 Image
👁 Image
👁 Image

Stop guessing about your digital experience with LogRocket

Get started for free

Recent posts:

Debug Next.js apps with AI agents and next-browser

Learn how next-browser gives AI agents runtime context for debugging Next.js apps, including React props, hydration, PPR, forms, and performance.

👁 Image
Emmanuel John
Jun 17, 2026 ⋅ 9 min read

Stop hardcoding LLM SDKs: Dynamic LLM routing with OpenRouter and Next.js

Build dynamic LLM routing in Next.js with OpenRouter, TanStack AI, task classification, model fallbacks, and cost-aware routing.

👁 Image
Chizaram Ken
Jun 16, 2026 ⋅ 13 min read

What is TSRX?: What JSX would look like if it were designed today

TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension — no new framework required.

👁 Image
Ikeh Akinyemi
Jun 12, 2026 ⋅ 6 min read

How to add authentication to a React Native app with Better Auth

Learn how to build a full React Native auth system using Better Auth and Expo — with email/password login, Google OAuth, session persistence, and protected routes.

👁 Image
Chinwike Maduabuchi
Jun 9, 2026 ⋅ 13 min read
View all posts

Would you be interested in joining LogRocket's developer community?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

Sign up now