A lot of React developers deal with state management while building their Applications, here is a guide on how to use Redux to manage those states.

When building medium or large-scale applications it's a better practice to use a State management system like Context or Redux.
In this guide, you will learn:
Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time-traveling debugger. In layman's terms, It's a state management system for javascript apps.
I personally recommend redux for medium/large scale applications and context for small applications.
In Redux you have to remember 3 things:
So in redux, you will create only one store and pass the store in your topmost react component. Normally in App Component in src/app.js file or index.js file. Store holds all the app state or global state for the application in Redux.
As the store will be passed to the React application or view part, we can pass any information or command. This is called action in the Redux way. That means you want to dispatch an action to send some command.
Basically the actions will be dispatched to the reducer which is a fancy term of function. The reducer will get the current state from the store and will use the actions to create a new state based on the old state and will update in the store.
Finally, if a view component is connected to the store, it will re-render when the state in the Redux store will be updated.
The first step is installing our dependencies from NPM, so on our command-line interface.
npm i redux react-redux redux-thunk redux-devtools-extension
Redux is stand-alone and react-redux gives us access to several hooks that make life easier, redux-thunk is a middleware that allows you to write action creators that return a function instead of an action, redux-devtools-extension is an optional dependency that I make use of to improve debugging and view states on the web.
A lot of people set up their folder structures in different ways with Redux, I like to create a redux folder and place my actions and reducers in separate folders within this particular folder, and a separate file in this folder for my types.

By the way, actions are objects that determine what will be done. Reducers, on the other hand, check which action is performed and update the state based on the action.
For the purpose of this article, we are building a small counter app.
Types.js) for clarity and reusability. Since we are building a simple project, it's quite easy to determine what all the types would be.//Types.Jsexport const INCREMENT = "INCREMENT";export const DECREMENT = "DECREMENT";export const RESET = "RESET";
counterReducer.js file inside the reducer folder you created earlier on.//counterReducer.jsimport { INCREMENT, DECREMENT, RESET } from '../Types.js'const initialState = {counter: 0}const counterReducer = (state = initialState, action) => {switch (action.type) {case INCREMENT:return {state,counter: state.counter + 1}case DECREMENT:return {state,counter: state.counter - 1}case RESET:return {state,counter: 0}default:return state;}}export default counterReducer
For the snippet of code above, we've basically created our reducer by defining its initial state and what happens when a particular action type is fired; A lot of people typically create the reducer with a switch statement, but it is also possible to use an if statement.
index.js file inside of our reducers folder, for an application with more than one reducer, we make use of the combineReducer function, this function turns our reducers into a single reducer that we can pass to the createStore API. Now our demo application only has one reducer, but for the purpose of subsequent projects we are going to make use of the combineReducer function.//Index.js(Reducer)import { combineReducers } from 'redux'import counterReducer from './counterReducer'export default combineReducers({counter: counterReducer})
store.js file inside of our src folder, see this as the logic and the connector between react and redux. To use the store, we are going to add it as a prop inside of a Provider that's going to wrap our entire application.//store.jsimport { applyMiddleware, createStore } from 'redux'import { composeWithDevTools } from 'redux-devtools-extension'import thunk from 'redux-thunk'import rootReducer from './redux/reducers'const initialState = {}const middleware = [thunk]const store = createStore(rootReducer,initialState,composeWithDevTools(applyMiddleware(...middleware)))export default store
store.js into Index.js://index.jsimport React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';//New codeimport { Provider } from 'react-redux'import store from "./store"ReactDOM.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>,document.getElementById('root'));
API calls happen too). Inside the actions folder, let's create counterActions.js.//counterActions.jsimport { INCREMENT, DECREMENT, RESET } from '../Types.js'export const increment = () => {return {type: INCREMENT,};};export const decrement = () => {return {type: DECREMENT,};};export const reset = () => {return {type: RESET,};};
import React from 'react';import './App.css';import logo from "./logo.svg"import { useSelector, useDispatch } from "react-redux";import { decrement, increment, reset, } from "./redux/actions/counterAction";const App =()=> {//dispatch is the hook to fire off our actionsconst dispatch = useDispatch();//useSelector helps access the states across the application.const counter = useSelector((state) => state.counter);return (<div className="App"><header className="App-header"><img src={logo} className="App-logaso" alt="logo" /><h1>Redux project</h1><h3>Counter</h3><h3>{counter.counter}</h3><button onClick={() => dispatch(increment())}>Increase</button><button onClick={() => dispatch(reset())}>Reset</button><button onClick={() => dispatch(decrement())}>Decrease</button></header></div>);}export default App;
Now we should have a fully working react-redux application.

We now have a fully running react-redux application, new reducers can be created in the reducers folder, actions created in the actions folder then connected to the combineReducers export.
While Redux is by far the popular and widely used state management system, I highly recommend using Redux for large and medium-sized applications alone.
There are other state management systems I've come across like Mobx, Context API, and Apollo for GraphQL to use at your disposal likewise.
I hope you enjoyed reading this and would be building your next Redux application without hassle.
Thanks to the creator of Redux and one of my Favorite Software developers, Dan Abramov
I'm Jide, a Full-Stack Software Engineer with penchant for Web/App development. I like scratching my own itch and writing about Web Technologies, UI/UX case studies, and Tech-bits thereof. During my spare time, I'm an autodidact polymath acquiring knowledge from various resources online.
© 2025 Jide Abdul-Qudus. All rights reserved.