Redux made easy with — RTK Query

Avishek Jana
GEOGO
Published in
6 min readOct 20, 2021

--

DX (Developer Experience) matters to you?

You’re managing the data fetching, caching and state management in Redux all by yourself?

Writing Redux logic in the same way, for quite a while?

Yes? Then you are at the right place and things are going to change in the next 5 minutes.

At GEOGO (our company), Redux is one of the most used JS library. It plays an important role in many front-end projects when it comes to application state management. While I was bootstrapping a new React application a month back, I checked Redux is now officially recommending all of us to use the Redux Toolkit, instead of their default approach.

When I studied more about this toolkit, I found that it allows us to write the state management logic more effortlessly. And I really mean it. Go check my previous article on Redux Toolkit — A fresh breeze in React ecosystem.

RTK Query is a part of Redux Toolkit. In this article I’ll show you, using RTK Query, how your DX can become 10x faster and UX would get an immense boost.

Web applications normally need to fetch data from a server in order to display it. They also usually need to make updates to that data, send those updates to the server, and keep the cached data on the client in sync with the data on the server. Apart from that they also have to implement other behaviours like:

  • Tracking loading state in order to show UI spinners
  • Avoiding duplicate requests for the same data
  • Optimistic updates to make the UI feel faster
  • Managing cache lifetimes as the user interacts with the UI

Over the last few years, the community has realized that the data fetching and caching is really a different set of concerns than state management. While you can use a state management library like Redux to cache data, it becomes difficult to handle other use cases mentioned above.

RTK Query is a powerful data fetching and caching tool. It is designed to simplify common cases for loading data in a web application, it eliminates the need to hand-write data fetching & caching logic yourself.

It takes inspiration from other tools that have pioneered solutions for data fetching, like Apollo Client, React Query etc.

Key aspects of RTK Query

  • RTK Query is built on top of the Redux Toolkit core, and leverages Redux Toolkit’s APIs like createSlice and createAsyncThunk to implement its capabilities.
  • Here, API endpoints are defined ahead of time, including how to pass query parameters and how to transform the API server’s response for caching.
  • RTK Query automatically generates hooks from the endpoints defined (I’ll show later how cool they are). These hooks can be called directly from the UI components to fetch and show data. Not only that, they also encapsulate the entire data fetching process, and provides data and isLoading fields to components.
  • RTK Query also support caching of data.
  • If two components in a single page are making a network call to the same endpoint defined in RTK Query, it detects that and make one single call instead.

Enough theory! It’s time to get our hands dirty

Let’s get started

If you’ve installed Redux Toolkit in your application, then RTK Query is already there bundled with the same package.

Step 1: Create an API Slice

So, let’s get started by creating an “API Slice” which would start with the server’s base URL and endpoints we want to interact with.

We have to define 3 key things here:

  1. reducerPath: We need this reducerPath when we would include this API Slice in configureStore.
  2. baseQuery: The base query will be used by each endpoint we would define next. RTK Query exports a utility called fetchBaseQuery as a lightweight wrapper around fetch for common use-cases.
  3. endpoints: Endpoints are just a set of operations that you want to perform against your server. There can two types of endpoint: query and mutation.
src/reduxStore/services/starWarsApi.js

In the above snippet, we’ve set our baseUrl to popular Star Wars API.

Note: Till this part, this is a one time setup. And it’s recommended to keep one single API file for all the possible endpoints, against one baseUrl.

Step 2: Add endpoints in API Slice

As I’ve said above, there can two types of endpoint: query and mutation. Let’s define our first query endpoint.

In the above snippet, we’ve added two different endpoints.

  1. getFilms: To get list of all films
  2. getFilmById: To find details of any specific film with its ID. In this case filmId is a query parameter, you can add more as per your need.

Step 3: Export auto-generated hooks for these endpoints

Now it’s time to see some magic. For every endpoint defined above, RTK Query generates hooks for them automatically. These hooks can be imported and directly used in UI components to fetch data. Let’s see it in action.

See how RTK Query auto-generates hooks for us

Just start typing with use.., and your editor would automatically suggest the newly generated hook’s name. The hook name also contains the type, whether it’s a Query or Mutation.

That’s dead simple, isn’t it?.

So the final version of Star Wars API Slice would be:

Final version of: src/reduxStore/services/starWarsApi.js

Step 4: Add API service to the root Redux store

An RTK Query service/slice generates a “slice reducer” that should be included in the Redux root reducer. Also, we have to enable a custom middleware that would handle the data fetching caching, invalidation, polling other useful features of RTK Query.

src/reduxStore/store.js

That’s it, our setup on Redux’s end in now complete. Next, we will use those hooks that we’ve just created in step 3, inside our UI components.

Step 5: Use RTK Query hooks in components

./components/FilmsList.jsx

Yes, it’s that simple

  • In Line №1, we’ve just imported the hook useGetFilmsQuery
  • In Line №5, we’ve called the query hook, and it automatically fetches data and returns query values.
  • When making a request, you’re able to track the state in several ways. You can always check data, status, and error to determine the right UI to render. In addition, useGetFilmsQuery also provides utility booleans like isLoading, isFetching, isSuccess, and isError for the latest request. Check the console log output of Line №6 once.

Isn’t it amazing

We’ve just eliminated the following steps than the normal Redux implementation.

  1. Now we don’t have to create separate action creators for each and every fetch queries, as we are defining one single API service for the whole baseUrl.
  2. No need to define multiple reducers and their switch cases.
  3. No need to handle different request states, like isFetching, isError etc.
  4. From UI components, we don’t have to dispatch actions or write selectors to get data from Redux store.

Time to see it in action

Easy steps for next time onwards

Once we’ve defined the initial API service (Step 1) and configured the store (Step 4), everything comes down to only two (yes 2) repetitive steps.

  1. Define the endpoint (in Step 2).
  2. Use the RTK Query hooks inside components as shown in Step 5.

Instant Benefits

  1. As I’ve promised in my previous article, development speed would be 10x Faster ⚡️️️️️️ for sure (my assumption).
  2. RTK Query eliminates redundant network calls for same endpoint.
  3. Caching comes out of the box, thus you will see massive improvement in user experience.

Wrap Up

Now at this point you may say,

Hey Avishek you’ve only shown us the example of query to read data, but what about the write operations or mutations?

Well, you are right, I haven’t talked about the mutation yet. I’ll publish another article with detailed implementation guides on RTK Query’s mutation (within a week after this article gets published). Subscribe to our newsletter, and get notified when that goes LIVE.

Thanks for reading!!

If you have any questions or suggestions regarding this article, feel free to comment down below. Peace!

--

--