# Create a Global State with React Context 🦾, No Redux, No third party library at all, pure React for Global State.

## What is React Context?

A typical React application consists of many Components, things get pretty complex as an application grows. If you are using props to pass `state` values from your parent component to the child component, things will become more complex pretty soon, and you will end up passing props to infinite levels down in your component tree, which makes debugging really complicated.

Then `Redux` or any other state management library enter into the play, but no matter how good are those, it is just another library to handle along with your pure React application. Considering that, React introduced `Context API` with React 16. Let's see what it is capable of.

## React Context and Redux:


> Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.

This is what React official docs have to say about React `Context`, Before we start talking about some code, let's have a look at what `Redux` provides that we can replicate in our application with React `Context`.

![redux-architecture.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1623491388340/EY_sQJ_vg.jpeg)

As you can see in the above picture, we have `actions`, `reducers`, and `store` to manage our state in `Redux`. You will not believe me, but we can achieve the same functionality with React `Context` as you move forward in this article. Let's break down the above image.

**Actions** - These are just `functions`, we call an action whenever we want to make changes in our application data, most of the time, these functions are simple API calls, which are capable to change the global state through `dispatch`.

**Reducer** - Aah! its name is really confusing for beginners, but no worries, these are also simple functions, which would take the old `state` and `action` as an argument and return the new `state` as an object.

**Store** - A store is an immutable object tree in Redux. You can think of it as a state container that holds the application's state.

**Now we have got the idea of `actions`, `reducer`, and `store`, let's jump into the coding.
**

## Let's create a `StoreProvider` HOC with React Context:

1. First We will Start a simple React App with the help of [`create-react-app`](https://create-react-app.dev/), run the command given below.
```bash
$ npx create-react-app context-demo
```

2. Just create a folder inside `src/` with the name `store`.

3. Create a file named `index.js` inside the `src/store/` folder.

4. Create a file named `reducer.js` inside the `src/store/` folder.

5. Let's write our `StoreProvider` HOC inside the `src/store/index.js` file.
    ```javascript
    import React from "react";
    import { reducer } from "./reducer";

    // Create a initial state object
    const initialState = {
        "name": "Gaurav",
    }

    // Create a context with initial state
    export const Context = React.createContext(initialState);

    // State Provider to wrap the whole application
    const StoreProvider = (props) => {
        const [state, dispatch] = React.useReducer(reducer, initialState);
        const { children } = props;

        return (
            <Context.Provider value={[state, dispatch]}>{children}</Context.Provider>
        );
    };

    // Default export the StoreProvider
    export default StoreProvider;
    ```

    **Explanation: ** First we have to create an initial `state` object to initialize the global `state` and `context`, you can keep it empty also. Then we need to create a `Context` using the initial `state` object. Once `context` creation is done, you can create your own `StoreProvider` component to wrap the whole application inside this `provider` and make your global `state` accessible everywhere in your application.

    You have also noticed that `React.useReducer` is using a `reducer` and `initialState` to initialize the `[state, dispatch]`. We have not created the `reducer` yet, let's jump into the next section to create a `reducer`.

## Create a Reducer to utilize the `useReducer` hook:

Let's start with the `reducer`, we are aware of how `reducer` works. Let's create one for our demo application. Just open the `reducer.js` that we have created in the last section and write this code.

```javascript
export const reducer = (state, action) => {
    // Check the type of action using switch-case
    switch (action.type) {
        // if action is 'CHANGE_MY_NAME'
        case 'CHANGE_MY_NAME':
            // return new immutable state object
            return {
                ...state,
                name: action.payload.name,
            };
        // default
        default:
            return state;
    }
};
```
**Explanation: ** This is a simple reducer, which is taking `state` and `action` as an argument and checking the `type` of `action` which has been dispatched then returning a new `state` object accordingly.


## Integrate the `StoreProvider` with our Application:

**Now that we have created our `StoreProvider` HOC and a `reducer`, it is time to use these things in our application do some cool stuff with them.**

1. Open your `src/index.js` file.

2. Import the `StoreProvider` component in this file.
    ```javascript
    import StoreProvider from "./store";
    ```

3. Now just wrap your `App` inside this `StoreProvider` like this.
    ```javascript
    <StoreProvider>
        <App />
    </StoreProvider>
    ```

Now we are all set up and ready to use the `state` and modify the `state`. Let's do some more cool stuff.

## Accessing the global state inside our components tree:

We can access the global `state` object in any of our `components` using the `context` that we have created, but we will do it in a much easier way by creating our own custom `hook`, Let's do it.

1. Open your `src/store/index.js` file again.

2. Write this code just above the `StoreProvider` component and below the `context` creation code.
    ```javascript
    export const useStore = () => {
       // Below line will return -> [state, dispatch]
       return React.useContext(Context);
    };
    ```

    **Explanation: ** We are creating a custom `hook` named `useStore`, which will return the current `state` and `dispatch` function to make `state` modifications through reducers.

    Let's see how it works in `App.js` component.

3. Open your `src/App.js` file and erase everything in this file, and write this code.
    ```javascript
    import React from 'react';
    import { useStore } from "./store";

    function App() {
        const [state, dispatch] = useStore();
        return <h1>{state.name}</h1>
    }

    export default App;
    ```
     **Explanation: ** The `initialState` object that we had created earlier in this article is being used in this code. `{state.name}` is coming directly from the global state. Hope you have got the idea of a global `state`. Similarly, you can use the global `state` from anywhere in your application.

But the trickier part is to make the modification in our global `state` through `actions` as we do in `redux`. But we have got that too, in the above code, you can see that `useStore` hook is also returning the `dispatch` function, which we will use to make the modification in our global `state` through `reducers` let's do it.


## Modifying the global state inside our components tree:

**Let's rewrite our `App.js` component with some new functionality.
**

```javascript
import React from 'react';
import { useStore } from "./store";

function App() {
    const [state, dispatch] = useStore();

    const handleChange = (event) => {
        dispatch({
          type: 'CHANGE_MY_NAME',
          payload: {
            name: event.target.value
          }
        })
    }

    return (
        <div>
            <input type="text" name="name" onChange={handleChange}/>
            <h1>{state.name}</h1>
        </div>
    )
}

export default App;
```

**Explanation: ** Now that you see this is the simplest use of `dispatch` to modify our global state. The `input` element is connected to `h1` element value indirectly through React `Context` and global `state`. In simple words, as you type in the `input` element, the value of global `state` will change using `dispatch`


## Conclusion:

React is great, React Context is also great, but when it comes to debugging the `Context`, that's the toughest part of it. If you are planning to use `context` in a large-scale React application, then `Redux` will be a much smarter choice because of the features that you will get with it.

You can use `context` whatever the way you want it to, you can also create some `actions` to perform an `API call, I am leaving this all up to you, it depends on how creative you are with your React skills


> Thanks for making it to the End of this article. If you found any mistakes in this article, please do inform me, I would appreciate it. 

That's it for today in this blog, if you are finding any difficulty following this blog, you can find the complete code example in this `codesandbox`, the link is given below.

---

## External Links:

- **Code Sandbox**
%[https://codesandbox.io/s/react-context-demo-rzh9u]

- **A Project of mine**
%[https://github.com/mnamegaurav/facematch]

> ***For more such crispy blogs daily, follow DevJunction, subscribe to our newsletter and get notified.***
> 

## Social Links

- **LinkedIn:** [https://www.linkedin.com/in/mnamegaurav/](https://www.linkedin.com/in/mnamegaurav/)
- **YouTube:** [https://www.youtube.com/c/devjunction](https://www.youtube.com/c/devjunction)
- **Website:** [https://gaurav.devjunction.in/](https://gaurav.devjunction.in/)
- **GitHub:** [https://github.com/mnamegaurav](https://github.com/mnamegaurav)
- **Instagram:** [https://www.instagram.com/mnamegaurav/](https://www.instagram.com/mnamegaurav/)
- **Twitter:** [https://twitter.com/mnamegaurav](https://twitter.com/mnamegaurav)
