Actions, Reducers, and Store in Redux

Loading

In Redux, Actions, Reducers, and the Store are fundamental components used to manage the application state. Let’s break down each of these concepts and how they work together to make state management predictable and structured in a Redux application.


1. Actions in Redux

An Action is a plain JavaScript object that describes an event or change that occurred in the application. Actions are used to communicate with the Redux store and describe what happened but don’t specify how the state is updated.

Key Points:

  • An action must have a type property, which describes the action.
  • Actions can also have additional payload data to provide more information.
  • Actions are typically dispatched to trigger state changes.

Example of an Action:

const addItemAction = {
  type: 'ADD_ITEM',
  payload: { id: 1, name: 'Item 1' }
};

Action Creator:

An Action Creator is a function that returns an action object. It helps to avoid directly creating action objects in your components and provides a way to standardize how actions are created.

const addItem = (item) => ({
  type: 'ADD_ITEM',
  payload: item
});

You can dispatch this action using store.dispatch(addItem(item)).


2. Reducers in Redux

A Reducer is a pure function that receives the current state and an action, and returns a new state. It defines how the state should change based on the action received. Reducers specify how the state should be updated when an action is dispatched.

Key Points:

  • Reducers should be pure functions, meaning they don’t mutate the state directly but return a new copy of the updated state.
  • Reducers handle a specific slice of state (e.g., items, user data).
  • Action type determines how the reducer updates the state.

Example of a Reducer:

const initialState = {
  items: [],
};

const itemsReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_ITEM':
      return {
        ...state,
        items: [...state.items, action.payload],
      };
    case 'REMOVE_ITEM':
      return {
        ...state,
        items: state.items.filter(item => item.id !== action.payload.id),
      };
    default:
      return state;
  }
};
  • In the above example, the ADD_ITEM action adds an item to the items array.
  • The REMOVE_ITEM action removes an item from the array by filtering it out.

3. Store in Redux

The Store is a central place where the entire state of the application is stored. It holds the application state, allows access to it, and provides methods to dispatch actions and subscribe to state changes.

Key Points:

  • The store holds the state of the application.
  • Only one store can exist in a Redux application, making it the “single source of truth.”
  • The store is created using the createStore() method (or configureStore() in Redux Toolkit).
  • Dispatching actions updates the store’s state, and the new state can be read using getState().

Example of Creating a Store:

import { createStore } from 'redux';

const store = createStore(itemsReducer); // Pass the reducer to the store

You can now access the state using store.getState() and dispatch actions using store.dispatch(action).

Example of Dispatching an Action:

store.dispatch(addItem({ id: 2, name: 'Item 2' }));

How Actions, Reducers, and Store Work Together

  1. Action Dispatching:
    • A component or UI element dispatches an action when something happens, e.g., a button click.
    • Example: When a user adds an item, an action like addItem() is dispatched.
  2. Reducer Handling:
    • The action is sent to the reducer. The reducer examines the action type and updates the state accordingly.
  3. Store Update:
    • The store updates its state with the new state returned by the reducer. React components can now access the updated state.

Example Workflow in Redux

  1. Action Creation: When a user clicks a button to add an item, an action is dispatched. store.dispatch(addItem({ id: 1, name: 'Item 1' }));
  2. Reducer Processing: The action reaches the reducer, which processes it and returns the updated state. const itemsReducer = (state = [], action) => { switch (action.type) { case 'ADD_ITEM': return [...state, action.payload]; default: return state; } };
  3. State Update: The store updates the state and React components are re-rendered based on the new state.
  4. Component Access: The component (using connect or useSelector in React-Redux) gets the updated state and renders it.

Full Example in Action

  1. Action Creator (actions.js): export const addItem = (item) => ({ type: 'ADD_ITEM', payload: item });
  2. Reducer (reducers.js): const initialState = { items: [] }; const itemsReducer = (state = initialState, action) => { switch (action.type) { case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }; default: return state; } }; export default itemsReducer;
  3. Store Setup (store.js): import { createStore } from 'redux'; import itemsReducer from './reducers'; const store = createStore(itemsReducer); export default store;
  4. React Component (App.js): import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { addItem } from './actions'; const App = () => { const dispatch = useDispatch(); const items = useSelector((state) => state.items); const handleAddItem = () => { dispatch(addItem({ id: 1, name: 'Item 1' })); }; return ( <div> <button onClick={handleAddItem}>Add Item</button> <ul> {items.map((item) => ( <li key={item.id}>{item.name}</li> ))} </ul> </div> ); }; export default App;

Leave a Reply

Your email address will not be published. Required fields are marked *