Lesson 24 / 25

Migrating Legacy Redux to Redux Toolkit

Incremental, one slice at a time.

No big-bang rewrite needed

Redux Toolkit is still Redux, so migration can be gradual. Step one: replace createStore, applyMiddleware and composeWithDevTools with configureStore, passing your existing root reducer; everything keeps working and you gain dev checks. Then convert one reducer at a time to createSlice, deleting hand-written action type constants and action creators. Replace connect with useSelector and useDispatch as you touch components (connect is still supported). Finally, replace hand-written data-fetching reducers and thunks with RTK Query endpoints, and remove sagas where a listener or thunk is enough.

Step one: swap the store setup

Old and new store.ts.

// BEFORE
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from '@redux-devtools/extension';
import todos from './reducers/todos';
import user from './reducers/user';

const store = createStore(
  combineReducers({ todos, user }),
  composeWithDevTools(applyMiddleware(thunk))
);

// AFTER: same reducers, thunk and DevTools included by default
import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
  reducer: { todos, user },
});

Expect the dev checks to find bugs

After switching to configureStore, the mutation and serialisability checks often reveal existing bugs such as mutated state or Dates and class instances in actions. Fix them rather than turning the checks off.

Quick check: What is a safe first step when migrating legacy Redux to RTK?

  • Switch to Zustand first
  • Rewrite every reducer in one pull request
  • Replace createStore with configureStore while keeping the existing reducers
  • Remove all middleware
Answer

Replace createStore with configureStore while keeping the existing reducers — configureStore accepts existing reducers, so the app keeps working.