DEV Community

Cover image for Is Redux Dead? Why I Kicked Redux Out of Our SaaS App
Subham
Subham

Posted on • Edited on

Is Redux Dead? Why I Kicked Redux Out of Our SaaS App

đŸ”„Connect: https://www.subham.online

đŸ”„GitHub: https://github.com/Subham-Maity

đŸ”„Twitter: https://twitter.com/TheSubhamMaity

đŸ”„LinkedIn: https://www.linkedin.com/in/subham-xam

đŸ”„Insta: https://www.instagram.com/subham_xam


A few months ago, I took the plunge and refactored parts of a SaaS app I’ve been working on for a while. We had Redux in there, doing its thing, managing global state. Even with the newer RTK Query approach, which streamlines Redux’s handling of server state, we found ourselves gravitating toward React Query for its straightforward setup and reduced boilerplate... You know, like when you carry around stuff in your backpack that you haven’t touched in months? That’s how it felt.
But as our app grew, so did the complexity. Redux started to feel less like a solution and more like a problem. We were writing more boilerplate than actual logic.

💡 The Redux Dilemma

One day, while battling yet another Redux-related bug, I stumbled upon React Query. I'd heard a lot of buzz around it, but I never thought it could completely replace Redux. Then I gave it a try.

Before (with Redux):

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const api = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    getUser: builder.query({
      query: (userId) => `users/${userId}`,
    }),
  }),
})

// Component with RTK Query
const UserProfile = ({ userId }) => {
  const { data, isLoading, error } = api.useGetUserQuery(userId);

  if (isLoading) return <Spinner />;
  if (error) return <Error message={error.message} />;
  return <UserInfo user={data} />;
};

Enter fullscreen mode Exit fullscreen mode

After (with React Query):

const useUserData = (userId) => {
  return useQuery(['user', userId], () => api.fetchUser(userId));
};

const UserProfile = ({ userId }) => {
  const { data, isLoading, error } = useUserData(userId);

  if (isLoading) return <Spinner />;
  if (error) return <Error message={error.message} />;
  return <UserInfo user={data} />;
};
Enter fullscreen mode Exit fullscreen mode

While both approaches might look similar in this simple example, React Query's simplicity shows in real-world applications. It doesn't require setting up stores or managing additional architectural patterns - it just works out of the box while giving you powerful caching and state management capabilities.

Instead of manually fetching data, writing reducers, dispatching actions, and then updating the store (old pattern of redux), React Query did most of that heavy lifting for us. Pair that with some well-crafted custom hooks, and we had a lean, mean state-management machine.

đŸ€” But Wait, Is Redux All Bad?

Now, don't get me wrong. Redux isn't the boogeyman. It's a powerful tool that has its place. If you're building an app with complex client-side state that needs to be shared across many unrelated components, If you’re working with deeply nested state, or if you need a more explicit control over the flow of your app but for 90% of cases, especially for handling server state, React Query + custom hooks is more than enough.

So, why the fuss? Sometimes, as devs, we fall into the trap of using what’s familiar, even when there are better tools out there. That’s what happened with me and Redux. I was stuck in my old ways, thinking Redux was the only way to manage state in larger apps. I mean, the whole internet was saying “Redux or bust!” right?

🎭 The Plot Twist

Here's the kicker: by choosing React Query over Redux (even modern Redux), we actually made our app MORE scalable. Counter-intuitive, right? But think about it – with React Query handling our server state and custom hooks managing local state, we had a clearer separation of concerns. Each part of our app became more modular and easier to reason about, without the overhead of Redux's architecture.

✅ Why We Still Choose React Query

  • Simplicity: React Query required fewer configurations and dependencies, allowing us to start quickly and avoid setup time.
    • You need to include Redux as a dependency
    • You need to set up Redux store configuration
    • It's integrated with Redux's architecture
  • Bundle Size: When you only need server state management, React Query offers a lighter solution since you don't need to include the entire Redux ecosystem
  • Flexibility: With React Query, managing server state felt more intuitive, especially for small, isolated pieces of server data.
  • Learning Curve: For teams not already using Redux, React Query often provides a gentler learning curve

🚀 Why This Approach is Correct:

RTK Query was developed to bridge the gap between Redux and modern server state tools like React Query. However, for server state management, React Query remains a more streamlined choice, offering specialized features for caching, background updates, and retries without Redux’s added setup. For global client state, you can combine React Query with lightweight libraries like Zustand or even use React's Context API. This approach avoids Redux’s heavier infrastructure, keeping your application’s state management both simpler and more performant by focusing React Query on server state and relying on lighter options for global client state.

🏁 Is Redux dead?

Honestly, in the last few months, I’ve seen very few cases where React Query didn’t meet my needs.

So, is Redux dead? Maybe not, but it's definitely not the all-star it used to be for handling server state in modern React apps.

The beauty of React Query lies in its focused approach to solving server state challenges without the additional complexity of a global state management system.

It's not about Redux being bad - it's about choosing the right tool for the job. In our case, React Query proved to be that tool. React Query bring a new level of simplicity and efficiency that’s hard to ignore. For those not tied to Redux, it might be worth exploring if React Query or other dedicated server state solutions could better meet your app’s needs."

So, there you have it. Our journey from Redux addiction to React Query enlightenment. It wasn't always easy – there were moments of doubt, late-night debugging sessions, and more than a few facepalms. But in the end, it was worth it.

The key isn't choosing what's popular or traditional - it's choosing what's right for your specific needs. For us, that was React Query, and we haven't looked back since.

If you're feeling bogged down by Redux in your own app, I encourage you to take a step back and ask yourself: do you really need it? You might be surprised by the answer.

sometimes less is more. Especially when it comes to state management. Now if you'll excuse me, I have some more reducers to delete. Happy coding!

You can also check: Learn RTK Query

Top comments (19)

Collapse
 
ignore_you profile image
Alex

IMO it's not really fair to compare vanilla Redux and specialized library. Through evolution of a product I work on for 5 years, we as a team came to conclusion, that boilerplate code should be reduced; that handling of a single request doesn't have to be so heavyweight: actions, reducers, sagas and so on. Yet, when you just try to migrate all the business logic to React Query, you instantly fail, you can't just add a new query to a feature that uses bunch of sagas that performs some chained requests. So, then the most preferred option is RTK Query, as it is still Redux and business logic doesn't fall apart from "just server state". And, if I'm not very wrong, it has pretty everything that React Query does, background refetching, caching, long polling etc. Never felt that something's missing, honestly.

Would I use RTK Query in a new project? Maybe, why not. You get a server-state manager and a global state manager in one box.

Would I use React Query with Zustand or something like that? Again, maybe, why not. It's a shiny new tools that cool kids are using.

Would I refactor all my entire codebase just to get rid of Redux, that is nicely wrapped in Redux Toolkit that encaplusates boilerplate? Can't see any reason why.

Collapse
 
codexam profile image
Subham

Our complete Redux removal wasn't just about reducing boilerplate - it led to cleaner architecture, better performance, and more maintainable code. For complex business logic and chained requests, React Query's mutation hooks and query invalidation patterns actually proved more powerful than Redux sagas.
The question isn't whether RTK Query can handle server state - it's whether carrying Redux's complexity is worth it when specialized tools do the job better. In our case, the refactor effort paid off significantly in long-term maintainability and developer productivity.

Collapse
 
blueomni profile image
PaweƂ

maybe use redux rtk from toolkit to ease some things :)

Collapse
 
codexam profile image
Subham • Edited

No, not really. I've used Redux Toolkit (RTK) with Redux Thunk extensively, and even wrote an article on it: Learn RTK Query in Next.js in 5 Minutes. While RTK is powerful, especially for global state management, I've found that React Query outperforms it in key areas like performance, simplicity, and scalability—particularly when dealing with server-side data. React Query’s approach to state management is far more intuitive, with automatic caching, background fetching, and minimal boilerplate. In most cases, about 90% of what you need can be handled efficiently through React Query, leaving Redux or Zustand for managing only the truly global client-side state. RTK, while effective, can feel messier due to the extra setup and less streamlined state synchronization.

Collapse
 
markerikson profile image
Mark Erikson

Hi, I'm a Redux maintainer.

If you're comparing "RTK" to React Query in terms of writing your own reducers and thunks for data fetching, yes, I agree there's a difference. But, we specifically teach using the purpose-built RTK Query data fetching and caching layer for data fetching in Redux apps, and we designed RTK Query to be very similar to React Query in terms of API, concepts, and usage.

Can you point to specific aspects where you feel RTK Query does not match React Query in terms of "performance, simplicity, and scalability"? Or is this just a comparison of React Query vs "RTK with writing my own logic"?

Thread Thread
 
codexam profile image
Subham

Thank you for taking the time to review and provide feedback.

I apologize for the wrong comparison in the original article. I've updated the article to properly compare RTK Query and React Query side by side.

The core differences I've found in practice are mainly around initial setup requirements and bundle size considerations when working with server-state focused applications. That said, both solutions are powerful and well-designed... the choice really depends on team requirements and existing architecture.

Really appreciate your input in helping make this article more accurate and valuable for the community.

Collapse
 
blueomni profile image
PaweƂ

I guess it's a matter of personal preference. But you did compare raw redux even without toolkit against library focused on making queries. If you want to judge something then compare rtk with react query and then make some conclusions. I don't say you are wrong, cause you can't be wrong by using what you like and feel good but you are comparing wrong things. Writing raw logic always must fail against library specialized in certain things.

Thread Thread
 
codexam profile image
Subham

I totally get your point! You’re absolutely right that it's important to compare tools on more equal footing. My focus was specifically on RTK Query versus React Query for server-side data management. In that context, I find React Query’s automatic caching, background re-fetching, and overall simplicity more efficient, especially when working with server-state-heavy apps.

That said, I still use Redux Toolkit for managing client-side global state in certain parts of my projects where it's necessary. I haven't abandoned it entirely—RTK definitely has its strengths for handling complex or shared state. But for server-side data, React Query often feels like the more streamlined solution.

At the end of the day, as you mentioned, it really comes down to personal preference and the specific needs of your project!

Collapse
 
drprime01 profile image
DrPrime01

Those are my thoughts exactly. RTK has fetchBaseQuery for handling API requests and it has background fetching and automatic caching too

Collapse
 
guhandelta profile image
Guhaprasaanth Nandagopal

You make a compelling case for using React Query as a modern alternative to Redux, especially when handling server state. Your explanation of the differences is clear and to the point, highlighting how React Query cuts down on boilerplate code and promotes a more declarative and maintainable style. For applications that depend heavily on fetching data from the server, React Query seems like the go-to choice, thanks to its built-in caching, background prefetching, and automatic data synchronization.

That said, it’s crucial to recognize that React Query shouldn’t be viewed as a complete substitute for Redux. While it excels in managing server state, it doesn’t handle client-side state—things like deeply nested local data, complex UI logic, or communication between components that don’t involve server data. Relying solely on React Query in these situations could lead to messy workarounds that aren’t ideal.

This is where libraries like Zustand and Jotai come into play. Zustand is easy to use with its simple API, making it great for managing the global client-side state effectively. On the other hand, Jotai’s atom-based system is perfect for modularizing state management for local or temporary needs. Using these tools alongside React Query seems like a smart way to stitch together a solution that addresses server and client state requirements.

To sum it up, React Query is fantastic for server state, but for apps that have significant client-side state requirements, adding Zustand or Jotai into the mix can create a more complete and safe solution, steering clear of the pitfalls where React Query might fall short on its own. This combination offers a modular and efficient way to manage the state without complicating things unnecessarily.

Collapse
 
codexam profile image
Subham

I already mentioned in the article we can pair React Query with something lightweight like Zustand or just stick to Context API. Way simpler than dealing with Redux with RTK Query setup

Collapse
 
peter-fencer profile image
Peter Vivo • Edited

Redux real replacement is useReducer, which is original, lightweight React state handling solution paired with commonly used useState. The Big difference is the useReducer working with reducer and actions so it is capable to handle a complex state handling instead useState just handle a single one.

If would like avoid dispatch passing and typesafe useReducer, feel free to try: jsdoc-duck ... maybe worth it.

But redux have own strength as battle tested global state handler library for Redux

Collapse
 
zohaib546 profile image
Zohaib Ashraf

Well I'm little confused here as React query is a data fetching library and not a state management library while Redux is state management library.
so in your example React query only helps to optimize the fetching part and eliminate useEffect in the component.
yes I agree using React query makes code more predictable and easier to understand
but what if this component also wants to share state under the deeper component where redux makes more sense and react query wont

Conclusion is Redux is not data fetching library but state management while React query is data fetching library not state management

Collapse
 
codexam profile image
Subham

I've found that a large portion (often 80%+) of what we traditionally put in Redux was actually server state - data fetched from APIs that we were manually syncing and caching. For the remaining client-side state that truly needs to be global, I've found that lighter solutions like Context + hooks or Zustand work well enough.
That said, there are absolutely valid use cases where Redux still shines:

  • Complex client-side state that needs to be shared across many unrelated components
  • State that requires precise control over updates and transformations
  • Scenarios where you need robust dev tools and time-travel debugging The key is choosing the right tool for the specific needs of your application rather than defaulting to Redux for everything. React Query for server state, and then evaluate whether you need Redux or a lighter solution for client state.
Collapse
 
rafaelramblas profile image
Rafael Ramblas

Redux is a global state manager, not an async state control library. In my project I use both, but redux is to hold information that needs to be accessible by any component, not to execute queries.

Collapse
 
codexam profile image
Subham

I've found that many teams (including mine) were using it as a catch-all solution, even for managing server data - which led to unnecessary complexity. The distinction between global state management and async state control is exactly why we moved away from Redux.
In our experience, about 90% of what we were storing in Redux was actually server state - data that React Query now handles much more elegantly with built-in caching, background updates, and synchronization. For the small amount of truly global client state we needed, simpler solutions like Context + custom hooks proved more than sufficient.
The question isn't whether Redux can store global state - it's whether we need that level of complexity for most modern web applications. After removing Redux, our codebase became more maintainable, our components more focused, and our state management more intuitive.

Collapse
 
kukiron profile image
Kafil Uddin Kiron

If you ended up removing part or most of redux code from your project then you probably shouldn't have used it to that extent in the first place. But comparing plain redux with react-query is a bit misleading.

Nonetheless, one should be careful before going full on with redux as it introduces new complexity. In a team environment, everyone keeps adding one more global state to redux store. And before you know it, it gets too big to handle.

Collapse
 
codexam profile image
Subham

We went overboard with Redux at first. You know how it goes ...you start putting everything in Redux just because it's there. True that comparing with plain Redux wasn't fair.. we actually used RTK Query and redux Toolkit before.
But after seeing our app getting messy, we switched things up. Now we just use React Query for API stuff and Zustand for the few things that actually need global state sharing.

The code's much cleaner now without all that extra Redux complexity!

Collapse
 
ashuto7h profile image
Ashutosh Sahu

I still like RTK query and it's best at what it does. with it's custom hooks and onQueryFulfilled promise, I was able to separate API response aftermath from components