Redux
Redux is a predictable state container for JavaScript applications. It helps manage application state consistently across different environments and simplifies testing. The current stable version is 5.0.1, which includes bug fixes and type adjustments. Redux maintains an active development cycle with regular patch releases and coordinated major updates, often alongside Redux Toolkit and React-Redux.
Common errors
-
Error: Actions may not have an undefined "type" property. Have you misspelled a constant?
cause An action was dispatched without a `type` property or with `type` as `undefined`/`null`.fixEnsure all dispatched actions have a `type` property set to a string value, e.g., `{ type: 'MY_ACTION' }`. -
Error: The reducer "myReducer" returned undefined when called with an undefined state. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.
cause A reducer returned `undefined` for its initial state, or when handling an action that it doesn't recognize.fixEnsure every reducer returns a valid state value (not `undefined`) for its initial state and for any action it does not handle explicitly. Always provide a default state parameter, e.g., `(state = initialState, action) => { ... }`. -
TS2304: Cannot find name 'PreloadedState'.
cause Attempting to use the `PreloadedState` TypeScript type, which was removed in Redux v5.fixUpdate your TypeScript code to remove references to `PreloadedState` and adjust the `Reducer` type signature to use its new generic argument for preloaded state if needed. -
'AnyAction' is deprecated.
cause Using the `AnyAction` TypeScript type, which has been deprecated in Redux v5.fixReplace `AnyAction` with the new `UnknownAction` type for better type safety. -
Error: Expected the last argument to be an enhancer. Instead received...
cause When calling `createStore`, multiple store enhancers were passed directly as arguments instead of being composed using `compose`.fixCombine multiple store enhancers into a single function using `compose` before passing them to `createStore`. Example: `createStore(reducer, compose(applyMiddleware(thunk), devToolsEnhancer))`.
Warnings
- deprecated The `createStore` function is officially deprecated in Redux v5. While still functional, new applications are strongly encouraged to use `configureStore` from `@reduxjs/toolkit`.
- breaking Actions dispatched to the store MUST have a `type` property that is a string. Non-string types for `action.type` are no longer permitted.
- deprecated The `AnyAction` TypeScript type has been deprecated in favor of `UnknownAction` to improve type safety.
- breaking The `PreloadedState` TypeScript type has been removed and replaced by a new generic argument for the `Reducer` type.
- gotcha The Redux team officially recommends using Redux Toolkit for all new Redux applications and most existing ones. Redux Toolkit simplifies common tasks, enforces best practices, and prevents common mistakes.
Install
-
npm install redux -
yarn add redux -
pnpm add redux
Imports
- createStore
import { createStore } from 'redux' - combineReducers
import { combineReducers } from 'redux' - applyMiddleware
import { applyMiddleware } from 'redux'
Quickstart
import { createStore } from 'redux';
interface AppState {
counter: number;
}
type Action = { type: 'INCREMENT' } | { type: 'DECREMENT' };
const initialState: AppState = { counter: 0 };
function reducer(state: AppState = initialState, action: Action): AppState {
switch (action.type) {
case 'INCREMENT':
return { ...state, counter: state.counter + 1 };
case 'DECREMENT':
return { ...state, counter: state.counter - 1 };
default:
return state;
}
}
const store = createStore(reducer);
console.log('Initial state:', store.getState());
store.dispatch({ type: 'INCREMENT' });
console.log('State after increment:', store.getState());
store.dispatch({ type: 'DECREMENT' });
console.log('State after decrement:', store.getState());
// Note: For new applications, it is highly recommended to use Redux Toolkit's `configureStore`
// and `createSlice` for a more efficient and simpler setup.