DEV Community

Mourya Vamsi Modugula
Mourya Vamsi Modugula

Posted on

๐Ÿง Do You Really Need Redux?

When people start learning React, they often hear: โ€œYou need Redux!โ€
But hereโ€™s the truth: not every app needs Redux.

Redux is great, but itโ€™s also extra code, setup, and concepts to maintain. Letโ€™s break it down.


โŒ When NOT to Use Redux

If your app is small, you probably donโ€™t need it.

Examples:

  • A to-do app where only one component manages state.
  • A theme toggle (dark/light mode).
  • A form where values donโ€™t need to be shared globally.

๐Ÿ‘‰ In these cases, just use Reactโ€™s built-in hooks:

// No Redux needed
import { useState } from "react";

export default function ThemeToggle() {
  const [dark, setDark] = useState(false);

  return (
    <button onClick={() => setDark(!dark)}>
      {dark ? "๐ŸŒ™ Dark Mode" : "โ˜€๏ธ Light Mode"}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

โœ… When Redux is a Good Choice

Redux shines in large apps with shared state across many components.

Examples:

  • An e-commerce app: cart items, user info, product filters.
  • A chat app: messages, notifications, online users.
  • A dashboard: global filters, real-time data, API caching.

Here, having one predictable place for state makes life much easier.


๐Ÿš€ Modern Redux = Redux Toolkit

If you do need Redux, donโ€™t write boilerplate reducers/actions manually.
Use Redux Toolkit (RTK) โ€” the official way to write Redux today.

Example: a simple counter:

// store/counterSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

interface CounterState {
  value: number;
}

const initialState: CounterState = { value: 0 };

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment: (state) => { state.value += 1 },
    decrement: (state) => { state.value -= 1 },
    addBy: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    }
  }
});

export const { increment, decrement, addBy } = counterSlice.actions;
export default counterSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

Hooking it up in a component:

import { useDispatch, useSelector } from "react-redux";
import { increment, decrement, addBy } from "./store/counterSlice";

export default function Counter() {
  const count = useSelector((state: any) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => dispatch(increment())}>โž•</button>
      <button onClick={() => dispatch(decrement())}>โž–</button>
      <button onClick={() => dispatch(addBy(5))}>+5</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Much cleaner than old Redux boilerplate ๐ŸŽ‰


๐Ÿ’ก Best Practices

  • Store only shared/global state in Redux.
  • Keep UI state (like modals, dropdowns) in local useState.
  • Use RTK Query for API data fetching & caching (built into Redux Toolkit).
  • Donโ€™t overcomplicate โ€” sometimes Context API is enough.

๐Ÿ”‘ Takeaway

Redux is not a must for every project.

  • Small apps โ†’ useState / useContext.
  • Medium apps โ†’ Context + hooks.
  • Large apps โ†’ Redux Toolkit for predictable state management.

๐Ÿ‘‰ Remember: The right use of Redux is knowing when not to use it.


Top comments (0)