How to setup and understand redux reducers and actions
I’m a big believer in analogies, and this article is aimed at helping you grasp the differences between reducers, actions and how to setup redux. If you rather skip the analogies, then skip the italicized text.
In the land of the web development seas, a band of pirates sailed the virtual waters in search of treasure and adventure.
These pirates were known as the Redux pirates and were feared and respected throughout the land for their prowess and skill in navigating the complex waters of state management.
1. Install redux & start sailing
npm i redux
npm i react-redux
2. Create the global store
In the ship's hold, the pirates stored all their treasure and supplies in a massive state object, guarded closely by the fierce Redux pirates.
- ⬇️ create a store file
src/store.ts
import { createStore } from "redux";
import rootReducer from "./reducers/index";
const store = createStore(rootReducer);
export default store;
3. Create Reducers
Under the captain’s command was a skilled quartermaster by the name of Reducer.
The quartermaster on a pirate ship is like a reducer in a React Redux application. Just as the quartermaster is responsible for managing the ship’s supplies and finances, the reducer is responsible for managing the state and data within the application.
The quartermaster keeps track of the crew’s share of the loot and treasure, and makes sure that it is distributed fairly. Similarly, the reducer keeps track of the state object and updates it correctly in response to actions dispatched by the React component.
- 🔽 create a root reducer file
src/reducers/index.ts
import { combineReducers } from "redux";
import pirateValuablesReducer from 'pirateValuablesReducer';
const rootReducer = combineReducers({
// TODO: combine reducers here
pirateValuablesReducer
});
export default rootReducer;
- 🔽 Next, create reducer files for each type of loot and valuables you want to store.
For example, here’s the pirateValuablesReducer
const initialState = {
gold: 0,
diamonds: 0,
pearls: 0,
treasureMaps: []
};
const pirateValuablesReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_GOLD':
return {
...state,
gold: state.gold + action.payload
};
case 'ADD_DIAMONDS':
return {
...state,
diamonds: state.diamonds + action.payload
};
case 'ADD_PEARLS':
return {
...state,
pearls: state.pearls + action.payload
};
case 'ADD_TREASURE_MAP':
return {
...state,
treasureMaps: [...state.treasureMaps, action.payload]
};
default:
return state;
}
};
export default pirateValuablesReducer;
4. Actions
The Redux Pirates are sailing the high seas in search of treasure. Whenever a pirate finds a treasure chest, they dispatch a message to the rest of the crew using a parrot. The message includes the type of treasure that was found (e.g. gold, diamonds, pearls) and the amount of treasure that was found.
In this analogy, the parrot is the action, and the message it carries is the payload. The type of treasure is the action type, and the amount of treasure is the payload. The quartermaster is the reducer, and they listen for messages from the parrot and update the Redux pirate’s stash of treasure accordingly.
export const addGold = (amount) => ({
type: 'ADD_GOLD',
payload: amount
});
export const addDiamonds = (amount) => ({
type: 'ADD_DIAMONDS',
payload: amount
});
export const addPearls = (amount) => ({
type: 'ADD_PEARLS',
payload: amount
});
export const addTreasureMap = (map) => ({
type: 'ADD_TREASURE_MAP',
payload: map
});
Each action is a simple function that returns an action object with a type
property and a payload
property. The type
property specifies the action type, and the payload
property specifies the value to be added to the corresponding state property in the reducer.
5. Components
The components in a React Redux application could be thought of as the pirates themselves. Just like the pirates, the components are the ones who go out and search for treasure (i.e. data). They use actions to communicate with the rest of the crew (i.e. the reducers) when they find treasure.
import { useDispatch } from 'react-redux';
import { addGold, addDiamonds, addPearls, addTreasureMap } from './actions';
const MyPirateComponent = () => {
const dispatch = useDispatch();
const handleAddGoldClick = () => {
dispatch(addGold(10));
};
const handleAddDiamondsClick = () => {
dispatch(addDiamonds(5));
};
const handleAddPearlsClick = () => {
dispatch(addPearls(3));
};
const handleAddTreasureMapClick = () => {
dispatch(addTreasureMap({
location: 'Island X',
clues: 'Look for the big palm tree with a red X painted on it.'
}));
};
return (
<div>
<button onClick={handleAddGoldClick}>Add 10 gold</button>
<button onClick={handleAddDiamondsClick}>Add 5 diamonds</button>
<button onClick={handleAddPearlsClick}>Add 3 pearls</button>
<button onClick={handleAddTreasureMapClick}>Add treasure map</button>
</div>
);
};
In this example, the useDispatch
hook is used to get a reference to the dispatch function, which is then passed to four event handlers that are called when the corresponding button is clicked. Each event handler dispatches an action to the store using the dispatch function.
For example, when the “Add 10 gold” button is clicked, the handleAddGoldClick
event handler is called, which dispatches the addGold
action to the store. This action updates the state by adding 10 to the current value of the gold
property in the reducer.
6. Use the store in your app
- ⬇️ Make the store available to your app. Modify your
src/index.tsx
file. Do the following: import { Provider } from 'react-redux;
import store from "./store";
- Wrap your
<App />
component with the provider and send it your importedstore
from yourstore.ts
file.
import { StrictMode } from "react";
import * as ReactDOMClient from "react-dom/client";
import { Provider } from "react-redux"; // Import the provider component.
import store from "./store"; // Import your store here.
import App from "./App";
const rootElement = document.getElementById("root");
const root = ReactDOMClient.createRoot(rootElement);
root.render(
<StrictMode>
<Provider store={store}> // <-- Add your provider here
<App />
</Provider>
</StrictMode>
);
As our band of hearty Redux pirates sail off into the sunset, we can’t help but feel grateful for the amazing power of actions and reducers. These trusty tools have helped us navigate the treacherous waters of state management and emerge victorious with a treasure trove of valuable data.