ionicons-v5-a Back
Can I use react-query and Redux together?
react

4 min read

Can I use react-query and Redux together?

Let's answer the question: Is it okay to integrate react-query into an existing Redux project?


The short answer is YES, it’s completely okay to start using react-query in the Redux project. However, let’s dive a bit deeper into the details.

In this article, we will talk about Redux, assuming you are using Redux Toolkit. If you weren’t using Redux Toolkit yet at all, you really should be! It will drastically simplify your code.

RTK Query

RTK Query solves the exact same use case and is designed to work great as part of Redux apps. RTK Query should be on your radar when you are considering adding a server layer to your application.

The choice actually depends on your goals. If you want to decrease the usage of Redux as a store or even remove Redux from your codebase by using a different data management tool (like Zustand, for example), then react-query will be the best option. If you plan to stick with Redux long-term, then you should probably consider using RTK since it’s a part of Redux Toolkit and it utilizes the Redux store object as a datastore for the data returned from the server.

React-query and Redux

If you’re still considering using react-query for adding it to your Redux project, or if you don’t use Redux Toolkit, or perhaps you simply prefer react-query more, that’s perfectly fine!

Keep in mind, though, that there may be a situation where you need data from the queryClient store inside a reducer (outside React component tree).

There are two ways to approach this:

  1. Either you send this data from the component level as a reducer payload.
  2. Or you import the query client directly into the reducer outside of the React component tree. (Why it’s not the preffered way you can read here)
// queryClient.ts
import { QueryClient } from 'react-query';
 
export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
      refetchOnWindowFocus: false,
    },
  },
});
// use useAppLimitations.ts
import { useQuery } from 'react-query';
import { AppLimits } from '@types';
 
export default function useAppLimitations() {
  return useQuery<AppLimits>(['app-limits'], () =>
    apiHttpService
      .get<AppLimits>('/api/license-limits')
      .then((res) => res.data),
  );
}
import { queryClient } from './app/queryClient';
 
ReactDOM.render(
  <QueryClientProvider client={queryClient} contextSharing>
    <Provider store={store}>
      <App />
    </Provider>
    <ReactQueryDevtools initialIsOpen={false} />
  </QueryClientProvider>,
  document.getElementById('root'),
);
// App.tsx
export default function App() {
  // contains maxTodosVisible available for user
  const { data: appPlanLimitations } = useAppLimitations();
}
// todos.slice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { SLICE_NAME } from './constants';
 
import { queryClient } from '@/app/queryClient';
 
interface TodosState {
  todos: TodoItem[];
}
 
const initialState: TodosState = {
  todos: [],
};
 
export const slice = createSlice({
  name: SLICE_NAME,
 
  initialState,
 
  reducers: {
    setTodos: (state, action: PayloadAction<TodoItem[]>) => {
      // let's imagine we need app limitations from query client store here
      // so we will need either send it from component as a payload
      // or import queryClient in this file
 
      const appPlanLimitations = queryClient.getQueryData<AppLimits>([
        'app-limits',
      ]);
 
      state.todos = action.payload.slice(0, appPlanLimitations.maxTodosVisible);
    },
  },
});
 
export const { setTodos } = slice.actions;
 
export default slice.reducer;

Conclusion

It is perfectly acceptable to use react-query with Redux, but depending on the direction you are taking with Redux, you should also explore alternative options. Once you integrate react-query into your Redux app, you may find that you gradually rely less on Redux, primarily utilizing it for scenarios where you need to persist specific UI data between views.


Dzmitry Kozhukh

Written by Dzmitry Kozhukh

Frontend developer


Next