Redux Cheatsheet



This Redux cheatsheet offers a concise reference to essential Redux concepts, including store creation, actions, reducers, and middleware. It covers advanced topics such as integrating Redux with React, handling async actions, and using the Redux Toolkit, with practical code examples for each feature. Designed for both beginners and experienced developers, this guide helps you quickly understand Redux's state management principles and its interaction with React.

Table of Contents

Introduction to Redux

Redux is a predictable state container for JavaScript apps, it is most commonly used together with React. It enables you to address all of your applications global state needs by providing a single store where actions and reducers control the state. Redux aids in an application by making its state more predictable, easier to test, and easier to debug.

Creating a Store

Initializes a Redux store using createStore(), defining an initial state and a reducer function to manage state updates.

Example:

import { createStore } from 'redux';

const initialState = { value: 0 };

function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { value: state.value + 1 };
    case 'DECREMENT':
      return { value: state.value - 1 };
    default:
      return state;
  }
}

const store = createStore(counterReducer);

Using a Store

Interacts with the store using methods like dispatch() to send actions, getState() to retrieve the current state, and subscribe() to listen for state changes.

Store Methods:

Method Description
store.dispatch() Dispatches an action to update the state.
store.getState() Retrieves the current state.
store.subscribe() Registers a listener to state changes.

Example:

store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // { value: 1 }

store.subscribe(() => {
  console.log('State changed:', store.getState());
});

React Redux Integration

Provider Component: The <Provider> component makes the Redux store available to React components.

Example:

import { Provider } from 'react-redux';

<Provider store={store}>
  <App />
</Provider>

Mapping State and Dispatch

Mapping State to Props: Maps the Redux state to component props.

Mapping Dispatch to Props: Maps dispatchable actions to props.

Example:

import { connect } from 'react-redux';

function App({ message, onMessageClick }) {
  return (
    <div onClick={() => onMessageClick('Hello')}>{message}</div>
  );
}

const mapStateToProps = (state) => ({
  message: state.message
});

const mapDispatchToProps = (dispatch) => ({
  onMessageClick: (msg) => dispatch({ type: 'MESSAGE_CLICK', message: msg })
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

Combining Reducers

Combining combineReducers() to merge multiple reducers into a single root reducer makes state management modular.

Example:

import { combineReducers } from 'redux';

const rootReducer = combineReducers({
  counter: counterReducer,
  user: userReducer
});

const store = createStore(rootReducer);

Middleware

Middleware enhances Redux by adding custom logic between dispatching actions and updating the state, such as logging or handling async operations.

Example :

const logger = (store) => (next) => (action) => {
  console.log('Dispatching:', action);
  const result = next(action);
  console.log('Next state:', store.getState());
  return result;
};

Applying Middleware: Use applyMiddleware() to add middleware to the Redux store.

Example:

import { applyMiddleware, createStore } from 'redux';

const enhancer = applyMiddleware(logger);
const store = createStore(counterReducer, enhancer);

Actions

Actions are plain JavaScript objects that describe a state change in Redux, containing a type property and optional payload.

Feature Description Code Example
Defining an Action Actions are plain objects with a type property.

const increment = { type: 'INCREMENT' };

Action Creator

Functions that return action objects.

function increment() { return { type: 'INCREMENT' }; }

Action with Payload

Actions can include a payload to pass additional data.

function addTodo(text) { return { type: 'ADD_TODO', payload: text }; }

Dispatching an Action

Use dispatch to send an action to the store.

dispatch(increment());

Reducers

Reducers are pure functions that take the current state and an action, then return a new state based on the action type.

Feature Description Code Example
Writing a Reducer

A reducer is a pure function that returns the new state based on the action type.

function counterReducer(state = 0, action) {

switch (action.type) {
case 'INCREMENT':
return state + 1;
default:
return state;
}
}

Handling Multiple Actions

Reducers handle multiple action types by using switch or if statements.

function counterReducer(state = 0, action) {

if (action.type === 'INCREMENT') return state + 1;
else if (action.type === 'DECREMENT') return state - 1;
return state;
}

Redux Toolkit

Simplifies Redux setup with built-in utilities like configureStore and createSlice.

Feature Description Code Example
configureStore A function to create the Redux store with automatic middleware setup.

import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: counterReducer
});

createSlice

Automatically generates action creators and reducers based on a slice of state.

const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
decrement: state => state - 1
}
});

createAsyncThunk

Simplifies the creation of async actions.

const fetchData = createAsyncThunk('data/fetch', async () => {
const response = await fetch('/data');
return response.json();
});

Async Actions

Explains handling asynchronous operations like API calls using middleware such as redux-thunk or redux-saga.

Middleware Description Code Example
redux-thunk A middleware to handle asynchronous actions.

const fetchData = () => dispatch => {
fetch('/data')
.then(response => response.json())
.then(data => dispatch({ type: 'DATA_FETCH_SUCCESS', payload: data }));
};

redux-saga

A middleware that handles async operations using generators.

function* fetchDataSaga() {
const data = yield call(fetch, '/data');
yield put({ type: 'DATA_FETCH_SUCCESS', payload: data });
}

Selectors

Selectors cover functions that retrieve and optimize access to specific pieces of Redux state.

Feature Description Code Example
Basic Selector A function that retrieves data from the store.

const selectCount = state => state.counter;

Reselect Selector

A memoized selector that computes derived data.

import { createSelector } from 'reselect';
const selectDoubleCount = createSelector(
[selectCount],
count => count * 2
);

Using Selectors in Components

Using useSelector hook to access state in React components.

import { useSelector } from 'react-redux';
const count = useSelector(selectCount);

Action Creators

Simple Action Creator: A function that returns an action object, making it reusable and reducing repetition in Redux applications.

const addToDo = (text) => ({ type: 'TODO_ADDED', payload: text });
store.dispatch(addToDo('Learn Redux'));

Asynchronous Action Creators: Functions that dispatch multiple actions, such as starting an API request and handling success or failure responses.

const fetchData = () => {
  return async (dispatch) => {
    dispatch({ type: 'FETCH_REQUEST' });
    const data = await apiCall();
    dispatch({ type: 'FETCH_SUCCESS', payload: data });
  };
}

Using bindActionCreators:

import { bindActionCreators } from 'redux';

const boundAddToDo = bindActionCreators(addToDo, store.dispatch);
boundAddToDo('Learn Redux');

React-Redux Hooks

Shows how to use react hooks like useSelector and useDispatch to interact with Redux in functional components.

Concept Code Example
Using useSelector

const count = useSelector((state) => state.counter.count);

Using useDispatch

const dispatch = useDispatch();

Dispatching Action

dispatch(addCount());

Using useSelector with Multiple Values

const count = useSelector((state) => state.counter.count);
const user = useSelector((state) => state.user);

Shallow Equality with useSelector

const { count, user } = useSelector((state) => ({
count: state.counter.count,
user: state.user
}), shallowEqual);

Old connect Version

import { connect } from 'react-redux';
export const Count = ({ count, addCount }) => ( ... );
const mapStateToProps = state => ({ count: state.counter.count });
const mapDispatchToProps = { addCount };
export default connect(mapStateToProps, mapDispatchToProps)(Count);

New useSelector + useDispatch

import { useDispatch, useSelector } from 'react-redux';
export const Count = () => {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(addCount())}>Increment</button>
<p>{count}</p>
</div>
);
};

Redux DevTools

Redux DevTools describes how to debug Redux applications with state inspection and time-travel debugging.

Feature Description Usage
Install Add DevTools to browser for debugging.

npm install --save-dev devtools-extension

Setup Store

Integrate DevTools in Redux store.

composeWithDevTools() in createStore()

Trace Actions View action call stack.

trace: true, traceLimit: 25

Skip Actions

Remove specific actions from timeline.

Use "Log Monitor" or "Inspector" in UI.

Jump to State

Navigate between states.

Use "Inspector" in DevTools.

Dispatch

Manually test actions.

Use "Dispatch" tab in DevTools.

Filter Actions

Allow/block actions in timeline.

actionsBlacklist: 'ACTION_TYPE'

Persist State Retain state across reloads. Click "Persist" or use ?debug_session= URL.
Lock State Freeze current state. Click "Lock" in DevTools.
Time Travel Replay state history. Use timeline controls in DevTools.

Testing

Explains testing Redux reducers, actions, and store behavior using assertions.

Component Code

Test Reducer

expect(reducer(state, action)).toEqual(expectedState)

Test Action

expect(actionCreator(payload)).toEqual(expectedAction)

Dispatch Action

store.dispatch(action(payload))

Assert State

expect(store.getState().key).toEqual(value)

TypeScript in Redux

Covers using TypeScript with Redux for better type safety and maintainability.

// Setup Store
import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

export type RootState = ReturnType<typeof store.getstate="">;
export type AppDispatch = typeof store.dispatch;

// Typed Hooks
import { useDispatch, useSelector } from 'react-redux';

export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: (state: RootState) => any = useSelector;

// Slice Example
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

interface CounterState {
  value: number;
}

const initialState: CounterState = { value: 0 };

const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

// Thunk Example
import { AppThunk } from './store';

export const fetchCounter = (): AppThunk => async (dispatch) => {
  const data = await fetch('/api/counter').then((res) => res.json());
  dispatch(incrementByAmount(data.value));
};

// Usage in Component
import React from 'react';
import { useAppSelector, useAppDispatch } from './hooks';
import { increment } from './counterSlice';

const Counter = () => {
  const count = useAppSelector((state) => state.counter.value);
  const dispatch = useAppDispatch();

  return (
    <div>
      <button onclick="{()" ==""> dispatch(increment())}>Increment</button>
      <p>{count}</p>
    </div>
  );
};

Redux-React

Redux-React tells how Redux is used in React applications to manage the global state.

Component Explanation Code
Store Creates Redux store. const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__());
Provider Links store to React. <Provider store={store}><App /></Provider>
mapStateToProps Maps state to props. const mapStateToProps = (state) => ({ counter: state });
mapDispatchToProps Maps actions to props. const mapDispatchToProps = (dispatch) => ({ increment: () => dispatch(increment()) });
connect Connects component to store. export default connect(mapStateToProps, mapDispatchToProps)(Counter);
Actions Redux actions. export const increment = () => ({ type: 'INCREMENT' });
Reducer Updates state. const reducer = (state = 0, action) => {
  switch(action.type) {
    case 'INCREMENT': return state + 1;
  }
};
Component Triggers Redux actions. <button onClick={increment}>INCREMENT</button>

Immutable State Management in Redux

Emphasizes the importance of keeping the Redux state immutable to prevent unintended mutations.

Tools Example Code
Return New State

return { ...state, counter: state.counter + 1 };

Spread Operator

todos: [...state.todos, action.payload]

Use Libraries

import produce from "immer";

Nested Update

return { ...state, nested: { ...state.nested, key: 'value' } };
Advertisements