How to create a Redux like pattern with Context API and useReducer
Tags: webdev, react, redux, context
Published: 2023-12-26 05:50:46

In most of the React js projects, we tend to use Redux for state management but sometimes we don't want to configure Redux in some of the applications, probably because the application size is not that big or we don't want to install too many third party libraries considering the bundle size.

Even without using Redux, we can configure the design pattern we use with Redux in our React application.

So in this tutorial, we will be using the Context Api and the useReducer hook.
If you are not aware of the Context API and the useReducer hook, you should check out the React official documentation before proceeding further. Just a basic understanding of these two will be enough.

## Step 1
Alright, in our react app directory, we will be creating one **store** folder, that will be responsible for holding all the redux-specific files. When I say redux, it is not a redux library but a kind of system that redux follows.


![Initial folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8pitacatsr74jla3hr9.png)

## Step 2
We will create a file **storeProvider.js** inside **store** folder and create a context and a component that will be just a wrapper of Context Provider.


![Store Provider initial setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fyql991m7ay9147r0c3.png)

## Step 3
Now that we have a StoreProvider, we can use this in our root file which is index.js as shown below.

![Providing in index](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i8h7b6jw4urld5u95ul.png)

## Step 4
Similar to useSelector in the react-redux library, we will be creating a custom hook that will be responsible for providing store values.
We will create a hook inside the store folder i.e. 'useStore.js'

![useStore custom hook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbvom3m02utn5ep7nopv.png)
And why we are using callback here, so sometimes we want to access specific property from the store object. If you recall useSelector hook, there we used to do something like 
`const users = useSelector(state => state.users);`
Similarly, we will be using,
`const users = useStore(state => state.users)`;

## Step 5
Now in our App component, we can verify the store values we are providing.
To do this, let's add a dummy state in our store, for that we will be updating our storeProvider as given below:

![Store provider with dummy state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vml5skk72scq97g5icq9.png)
And then in the app.js component(we can use any nested component), we can update as shown below:

![App js with useStore](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc3cc9xvxgr5e8se3oww.png)
Now, if we check the browser's console, we will get the logs for the state.

![dummy state logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqyn3yatj7iy08k2h33e.png)

## Step 6
So far, we have used hard-coded store property, but in real applications, we have many reducers. So, we will be creating our two reducers(count and users) inside a '/store/reducers/' folder.

![Count reducer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9voyu6t8ocz122kp5dg.png)

![users reducer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xtc3dr4dj7ppxsmsqqq.png)

## Step 7
It's time to use the useReducer hook, for that we will have to update the storeProvider and we will be passing **dispatch** object in context value.

![useReducer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y7pqnnittfdzd0c7zkrb.png)

## Step 8
You might have noticed, that we used **rootReducer** function, the reason behind that is we can not pass multiple reducers in the useReducer hook, so we need to find a way to combine multiple reducers into one reducer i.e. rootReducer.
We will create one index.js file in '/store/reducers' as given below:

![Root reducer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kuccc2abeas34wa0z280.png)
The parameters we are passing inside reducers are their state and our dispatch action object. Since we will be having switch cases in each reducer, it won't impact the count reducer even if it gets the users' action object. 

## Step 9
To verify this, we can configure our React App component

![React app component with dispatch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqneu91b0qp4hrl9uwv7.png)

![Final logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rvzjz6wpm9danlpbvpg6.png)

When we click on 'Increment' button, we will notice we are getting both store values.

Now we have successfully configured Redux free global store management system.