Redux Cheatsheet
A complete guide to Redux state management with simple examples. Learn how to manage your app's data with Redux and Redux Toolkit.
Store Setup
Create Store (Basic)
Set up a basic Redux store with DevTools. The store holds your app's data and lets you track changes. DevTools help you debug your app in the browser.
import { createStore } from 'redux'
import rootReducer from './reducers'
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
)
Configure Store (Redux Toolkit)
Modern way to create a Redux store using Redux Toolkit. It automatically sets up DevTools and includes common middleware. This is the recommended way to start new projects.
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(logger)
})
Actions
Action Creators
Actions are like messages that tell Redux what changes to make. Action creators are functions that create these messages. Here's how to create basic actions for a todo list.
// Action Types - Names for different actions
const ADD_TODO = 'ADD_TODO'
const TOGGLE_TODO = 'TOGGLE_TODO'
// Action Creators - Functions that create actions
const addTodo = (text) => ({
type: ADD_TODO,
payload: { text, id: Date.now() }
})
const toggleTodo = (id) => ({
type: TOGGLE_TODO,
payload: id
})
Create Slice (Redux Toolkit)
A slice combines actions and reducers in one place. It's an easier way to write Redux code. This example shows how to manage a todo list with Redux Toolkit.
import { createSlice } from '@reduxjs/toolkit'
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
addTodo: (state, action) => {
state.push({
id: Date.now(),
text: action.payload,
completed: false
})
},
toggleTodo: (state, action) => {
const todo = state.find(todo => todo.id === action.payload)
if (todo) {
todo.completed = !todo.completed
}
}
}
})
Reducers
Basic Reducer
Reducers are functions that update your app's data. They take the current state and an action, then return the new state. This example shows how to manage todos with a basic reducer.
const initialState = {
todos: [],
loading: false,
error: null
}
function todoReducer(state = initialState, action) {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, action.payload]
}
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map(todo =>
todo.id === action.payload
? { ...todo, completed: !todo.completed }
: todo
)
}
default:
return state
}
}
Combine Reducers
When your app grows, you can split reducers into smaller parts. combineReducers lets you join them back together. Here's how to combine separate reducers for todos and filters.
import { combineReducers } from 'redux'
import todosReducer from './todosReducer'
import filtersReducer from './filtersReducer'
const rootReducer = combineReducers({
todos: todosReducer,
filters: filtersReducer
})
export default rootReducer
Selectors
Basic Selectors
Selectors are functions that get specific data from the Redux store. They help you access and filter data easily. Here are examples of different types of selectors.
// Get all todos
const selectTodos = state => state.todos
// Get only completed todos
const selectCompletedTodos = state =>
state.todos.filter(todo => todo.completed)
// Get todos based on a filter
const selectFilteredTodos = state => {
const todos = selectTodos(state)
const filter = state.filters.status
switch (filter) {
case 'completed':
return todos.filter(todo => todo.completed)
case 'active':
return todos.filter(todo => !todo.completed)
default:
return todos
}
}
Create Selector
createSelector helps make your selectors faster by remembering previous results. It only recalculates when necessary. This is useful when filtering or transforming data.
import { createSelector } from '@reduxjs/toolkit'
const selectTodos = state => state.todos
const selectFilter = state => state.filters.status
const selectFilteredTodos = createSelector(
[selectTodos, selectFilter],
(todos, filter) => {
switch (filter) {
case 'completed':
return todos.filter(todo => todo.completed)
case 'active':
return todos.filter(todo => !todo.completed)
default:
return todos
}
}
)
Middleware
Custom Middleware
Middleware lets you add custom behavior when actions happen. This example shows how to create a logger that prints actions and state changes to the console for debugging.
const logger = store => next => action => {
console.group(action.type)
console.log('prev state', store.getState())
console.log('action', action)
const result = next(action)
console.log('next state', store.getState())
console.groupEnd()
return result
}
// Add middleware to store
import { createStore, applyMiddleware } from 'redux'
const store = createStore(
rootReducer,
applyMiddleware(logger)
)
Thunk Middleware
Thunk middleware lets you write actions that do async work like API calls. This example shows how to fetch todos from a server and handle loading states.
// Async action to fetch todos
const fetchTodos = () => async dispatch => {
// Show loading state
dispatch({ type: 'FETCH_TODOS_REQUEST' })
try {
// Make API call
const response = await api.get('/todos')
// Update state with data
dispatch({
type: 'FETCH_TODOS_SUCCESS',
payload: response.data
})
} catch (error) {
// Handle error
dispatch({
type: 'FETCH_TODOS_FAILURE',
error: error.message
})
}
}
// Set up store with thunk
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(logger)
})