Redux Toolkit

A Predictable State Container

Manage complex global state with a single source of truth. Data flows in one direction: Action → Reducer → Store.

Redux Toolkit

A predictable state container for JS apps. It helps you write applications that behave consistently, run in different environments, and are easy to test.

One-Way Data Flow

The core principle: Data flows in a single direction. UI triggers an Action, Reducer processes it, Store updates, UI re-renders.

The Formula

Reducers are pure functions. They take the current state and an action, and return the new state. They are the 'brain' of Redux.

Try It Out

Dispatch actions to update the store. Notice how the 'Action' travels to the 'Reducer' before the 'Store' updates.

Redux vs Context

When should you use which? A side-by-side breakdown of features and trade-offs.

Performance: Updates

Redux Selectors ensure only components that need the new data re-render. Context updates can trigger wider re-renders.

1. Create a Slice

With Redux Toolkit (RTK), we define "Slices". A slice contains the reducer logic and actions for a specific feature.

counterSlice.ts
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => {
      // Immer lets us "mutate" logic in reducers!
      state.value += 1;
    },
    decrement: state => {
      state.value -= 1;
    }
  }
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
Modern Redux Logic

2. Configure Store

Combine all your slices into the central store.

store.ts
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
    // user: userReducer,
    // cart: cartReducer...
  },
});
Create the Vault

3. Dispatch & Select

Use `useSelector` to read from the store, and `useDispatch` to send actions.

CounterComponent.tsx
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from './counterSlice';

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

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  );
}
Connect to Redux

When to use Redux?

Don't use Redux for everything! Use it when:

  • You have large amounts of application state to manage.
  • The state is updated frequently over time.
  • The logic to update that state may be complex.
  • You need "time-travel" debugging (Redux DevTools are amazing).

Redux vs useReducer + useContext

React's built-in hooks can do a lot, but Redux offers more structure for complex apps.

FeatureRedux ToolkitContext + useReducer
State LocationSingle External StoreReact Component Tree
PerformanceOptimized (Selectors)Requires Manual Optimization
DevToolsExcellent (Time Travel)Basic (React DevTools)
MiddlewareBuilt-in (Thunk, Saga)Manual Implementation
AlgoAnimator: Interactive Data Structures