Design Converter
Education
Last updated on Apr 4, 2025
•5 mins read
Last updated on Apr 4, 2025
•5 mins read
Software Development Executive - I
He writes code, breaks things, fixes them, and then does it all over again!
When working with modern frontend applications, keeping data in sync with the server without compromising performance or user experience is a constant challenge. This is where RTK Query Refetch plays a pivotal role, allowing developers to control how and when their application communicates with the backend.
In this technical blog, we will examine how to fetch data using RTK Query, control the cache, handle error scenarios, and effectively leverage query hooks, mutation endpoints, and trigger functions. This article aims to demonstrate best practices grounded in real-world experience while adhering to the principles of Redux Toolkit, React Redux, and robust data fetching logic.
RTK Query is a powerful data fetching and caching tool in the Redux Toolkit. One of its most powerful features is the ability to refetch data from the server when necessary. Whether you're updating cached data, reacting to user interactions, or triggering updates from mutation endpoints, RTK Query provides the flexibility to manage your query lifecycle confidently.
RTK Query refetching allows a component or function to manually or automatically re-run a query to fetch the latest data.
You begin by defining your API slice using createApi from @reduxjs/toolkit/query/react
.
1// src/services/postsApi.ts 2import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; 3 4export const postsApi = createApi({ 5 reducerPath: 'postsApi', 6 baseQuery: fetchBaseQuery({ baseUrl: '/api' }), 7 tagTypes: ['Post'], 8 endpoints: (builder) => ({ 9 getPosts: builder.query<Post[], void>({ 10 query: () => '/posts', 11 providesTags: ['Post'], 12 }), 13 addPost: builder.mutation<void, Post>({ 14 query: (post) => ({ 15 url: '/posts', 16 method: 'POST', 17 body: post, 18 }), 19 invalidatesTags: ['Post'], 20 }), 21 }), 22}); 23 24export const { useGetPostsQuery, useAddPostMutation } = postsApi;
This API slice defines both a query endpoint and a mutation endpoint for working with posts.
Every query hook returned by createApi provides a refetch function to trigger a refetch data operation manually.
1const { data, error, isLoading, refetch } = useGetPostsQuery(); 2 3return ( 4 <div> 5 <button onClick={() => refetch()}>Refetch Posts</button> 6 {isLoading && <p>Loading...</p>} 7 {error && <p>Error occurred</p>} 8 <ul>{data?.map(post => <li key={post.id}>{post.title}</li>)}</ul> 9 </div> 10);
Sometimes you want to re-run a query when the component mounts or the query parameters change.
1const { data } = useGetPostsQuery(undefined, { 2 refetchOnMountOrArgChange: true, 3});
This automatically triggers fetches when needed to maintain up-to-date cached data.
Refetch when the page gains focus or when the network reconnects.
1const { data } = useGetPostsQuery(undefined, { 2 refetchOnFocus: true, 3 refetchOnReconnect: true, 4});
This provides more flexibility for real-time-like data behavior without polling.
Knowing the status of a query helps provide proper user feedback and control over your UI.
1const { data, isLoading, isError, error, isSuccess } = useGetPostsQuery(); 2 3if (isLoading) return <p>Loading...</p>; 4if (isError) return <p>{error.status}: {error.message}</p>;
Track request status, handle error gracefully, and avoid rendering inconsistent data.
When mutations occur, it's best to invalidate stale cached data.
1const [addPost, { isLoading, error }] = useAddPostMutation(); 2 3const onSubmit = async (post: Post) => { 4 await addPost(post); 5};
This triggers cache invalidation for the 'Post' tag, causing the getPosts query to automatically refetch the latest data.
To validate your refetching logic:
Simulate user interaction with the refetch button.
Inspect Redux store for updated data.
Confirm new server responses are returned.
1it('refetches posts on button click', async () => { 2 render(<Posts />); 3 fireEvent.click(screen.getByText('Refetch Posts')); 4 expect(await screen.findByText('Post Title 1')).toBeInTheDocument(); 5});
Technique | Purpose | Example |
---|---|---|
skip | Skip query based on a condition | skip: userId === null |
refetchOnMountOrArgChange | Re-run query on arg change | refetchOnMountOrArgChange: true |
selectFromResult | Control re-renders with specific data | Select specific part of the query result |
trigger | Manually trigger a query | useLazyQuery() |
1const [trigger, { data, isLoading }] = useLazyGetPostsQuery(); 2 3<button onClick={() => trigger()}>Load Posts</button>
This pattern is ideal for pages where fetching occurs only after a user action.
Best Practice | Description |
---|---|
Use refetch to update data manually | Helps with precise control |
Handle isLoading, error, and data states explicitly | For clear UX |
Invalidate cache with mutations | Keeps cached data in sync |
Use refetchOnFocus / refetchOnReconnect sparingly | Avoid excessive fetch overhead |
Prefer useLazyQuery for on-demand fetch | Avoids unnecessary loading |
• Relying solely on cache: If server data changes, you need a plan for prefetching or cache invalidation.
• Ignoring error boundaries: Always check isError and handle error.response
or error.status
.
• Overfetching: Using refetchOnMountOrArgChange indiscriminately may cause repeated fetch data operations.
Understanding how to efficiently refetch data using RTK Query can drastically improve your component behavior and user experience. Whether you're building a page that needs to show the most current data, or managing complex interactions between query endpoints, mutations, and the redux store, mastering this behavior ensures your app always shows relevant and accurate data.
By responsibly using trigger functions, fetch logic, and mutation endpoints, you can keep server and client states aligned, maintain clean cached data, and reduce unnecessary fetches.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.