Redux made easy with — RTK Query
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
andcreateAsyncThunk
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
andisLoading
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:
reducerPath
: We need thisreducerPath
when we would include this API Slice inconfigureStore
.baseQuery
: The base query will be used by each endpoint we would define next. RTK Query exports a utility calledfetchBaseQuery
as a lightweight wrapper aroundfetch
for common use-cases.endpoints
: Endpoints are just a set of operations that you want to perform against your server. There can two types of endpoint:query
andmutation
.
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.
getFilms
: To get list of all filmsgetFilmById
: To find details of any specific film with its ID. In this casefilmId
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.
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:
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.
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
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
, anderror
to determine the right UI to render. In addition,useGetFilmsQuery
also provides utility booleans likeisLoading
,isFetching
,isSuccess
, andisError
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.
- 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
. - No need to define multiple reducers and their switch cases.
- No need to handle different request states, like
isFetching
,isError
etc. - 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.
- Define the endpoint (in Step 2).
- Use the RTK Query hooks inside components as shown in Step 5.
Instant Benefits
- As I’ve promised in my previous article, development speed would be 10x Faster ⚡️️️️️️ for sure (my assumption).
- RTK Query eliminates redundant network calls for same endpoint.
- 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 ormutations
?
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!