DEV Community

Cover image for Understanding Redux Internals: How It Works Under the Hood
Anurag Jain
Anurag Jain

Posted on

1

Understanding Redux Internals: How It Works Under the Hood

Redux is a widely used state management library in the React ecosystem, known for its predictable state updates and unidirectional data flow. While most developers use Redux with actions, reducers, and the useSelector/useDispatch hooks, few dive deep into how Redux actually works under the hood.

In this blog, we’ll peel back the layers of Redux and explore its core principles, including how actions are processed, how reducers update the state, and how the store efficiently notifies subscribers. By the end, you’ll have a deeper understanding of Redux’s internals, allowing you to debug issues more effectively and even build a simplified version of Redux yourself!

Let’s dive in. 🚀


Breaking Down Redux: Core vs React Bindings

To truly understand Redux under the hood, we need to separate its two key parts:

1. Redux Toolkit (RTK) – The Core of Redux

Redux itself is a standalone state management library that works independently of React. Redux Toolkit (RTK) is the modern way to use Redux, providing a more convenient API while keeping the core principles intact. It consists of:

  • Store – The centralized state container
  • Reducers – Pure functions that determine how the state changes
  • Actions – Descriptive objects that trigger state updates
  • Middleware – Custom logic that intercepts dispatched actions
  • Immer & Redux-Thunk – Built-in utilities for immutability and async logic

2. React-Redux – Connecting Redux to React

While Redux is framework-agnostic, React-Redux is the official binding library that integrates Redux with React components. It provides:

  • Provider – Makes the Redux store accessible to the React app
  • useSelector – Fetches state from the store within a component
  • useDispatch – Allows dispatching actions from components
  • Context-based optimizations – Ensures efficient re-renders in React

By understanding these two parts separately, you’ll gain a clear picture of how Redux and React-Redux work together to manage state efficiently.


Redux Toolkit (RTK) – The Core of Redux

At its heart, Redux operates on the publish-subscribe (pub-sub) pattern. The core idea is simple:

  1. A store holds the global state.
  2. Dispatching an action tells Redux that something has changed.
  3. The store calls the appropriate reducer, which updates the state immutably.
  4. Once the state is updated, all subscribed listeners are notified, allowing them to take action based on the change.

This predictable data flow ensures that state updates remain centralized, immutable, and traceable.

Breaking Down the Core Redux Flow

  1. Store Creation
    • Redux maintains a single store that holds the application’s state.
    • The store is created using configureStore() in Redux Toolkit or createStore() in vanilla Redux.
  2. Dispatching an Action

    • When an event occurs (like a button click), we dispatch an action (a plain JavaScript object with a type property).
    • Example:

      store.dispatch({ type: 'counter/increment' });
      
  3. Reducers Process the Action

    • The store passes the current state and the action to the reducer function, which returns a new state.
    • Redux Toolkit simplifies this using createSlice(), where reducers are auto-generated.
    • Example reducer:

      const counterSlice = createSlice({
        name: 'counter',
        initialState: { value: 0 },
        reducers: {
          increment: (state) => { state.value += 1; },
          decrement: (state) => { state.value -= 1; }
        }
      });
      
  4. State Updates & Listeners Get Notified

    • After the state is updated, Redux notifies all subscribed components or middleware, allowing them to react to the change.

Why Immutability Matters

Redux ensures that state is never mutated directly. Instead, reducers return a new copy of the state. Redux Toolkit simplifies this by using Immer, which allows us to write "mutating" code that is safely converted to immutable updates behind the scenes.


React-Redux – Connecting Redux to React

Redux is a framework-agnostic state management library, meaning it doesn't depend on React. However, in a React application, we need a way to connect Redux to components efficiently. This is where React-Redux comes in.

At its core, React-Redux relies on React Context and React’s built-in hooks to provide seamless state management. Let’s break it down:

How Redux Store is Provided to React Components

  • The Redux store is stored in a React Context that wraps the entire app.
  • The Provider component from React-Redux is simply a wrapper around this Redux context provider.
  • This allows any component within the app to access the Redux store without passing props manually.

Example: How Provider Works

import { Provider } from "react-redux";
import { store } from "./store";
import App from "./App";

const Root = () => (
  <Provider store={store}>
    <App />
  </Provider>
);
Enter fullscreen mode Exit fullscreen mode

Internally, Provider stores the Redux store inside a React Context and makes it accessible to all components.


How useSelector Works Under the Hood

The useSelector hook is responsible for selecting a piece of state from the Redux store inside a component.

How It Works:

  1. It gets the Redux store from context
  2. It subscribes to state updates using useSyncExternalStore, a built-in React hook for listening to external stores
  3. It extracts only the relevant part of the state (to optimize performance)

Example: Using useSelector

import { useSelector } from "react-redux";

const Counter = () => {
  const count = useSelector(state => state.counter.value);
  return <div>Count: {count}</div>;
};
Enter fullscreen mode Exit fullscreen mode

Why useSyncExternalStore?

  • React-Redux used to rely on useEffect and useState for subscriptions, but this led to performance issues and stale state bugs.
  • useSyncExternalStore ensures that React always reads the latest state and minimizes unnecessary re-renders.

How useDispatch Works Under the Hood

The useDispatch hook allows components to dispatch actions to the Redux store.

How It Works:

  1. It gets the Redux store from context
  2. It returns the store’s dispatch function

Example: Using useDispatch

import { useDispatch } from "react-redux";
import { increment } from "./counterSlice";

const IncrementButton = () => {
  const dispatch = useDispatch();
  return <button onClick={() => dispatch(increment())}>Increment</button>;
};
Enter fullscreen mode Exit fullscreen mode

Unlike useSelector, useDispatch does not subscribe to state changes—it only provides the dispatch function.


Optimisations in React-Redux

  1. Context is only used for accessing the store, not state updates
    • Redux’s state changes do not trigger unnecessary re-renders like regular React Context.
  2. useSelector prevents unnecessary re-renders
    • Components only re-render when the selected state changes, thanks to useSyncExternalStore.

Wrapping Up: Understanding Redux Inside Out

By now, you should have a clear understanding of how Redux and React-Redux work under the hood. We explored:

Redux Toolkit (RTK) – The core state management logic built on the pub-sub model, where a store holds the state, reducers handle updates immutably, and subscribed listeners react to changes.

React-Redux – The binding layer that efficiently connects Redux to React using React Context and hooks like useSelector and useDispatch, leveraging useSyncExternalStore for optimal reactivity.

Understanding these internals helps you:

🔹 Debug complex state issues with confidence

🔹 Optimize performance by avoiding unnecessary re-renders

🔹 Customize Redux behavior or even build your own minimal Redux-like system

At the end of the day, Redux is just a predictable state container with a well-defined flow. While libraries like Redux Toolkit and React-Redux make it easier to use, the core principles remain simple: dispatch an action → reducer updates the state → components react accordingly.

Next time you're using Redux, take a moment to appreciate the elegant architecture behind it.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay