In React, the global state refers to data that can be accessed and shared by multiple components in an application. It allows different parts of the application to communicate and stay in sync with each other by using the same data.
To manage global state in React, there are different approaches:
- React Context API: React provides a way to create a global state using the Context API. It lets you define the data that should be shared globally and make it available to any component. Components can then use or update this global state when needed. The Context API is useful for smaller projects or when you don’t need advanced features.
- State management libraries: For larger and more complex projects, you can use state management libraries like Redux, MobX, or Zustand. These libraries offer more advanced features and help you manage the global state efficiently. They follow a specific pattern where components can update the state, and other components can subscribe to changes and react accordingly.
It’s important to use global state carefully and only when necessary. Using it too much can make your code complex and harder to maintain. So, consider the size and complexity of your application before deciding to use global state.
Prop drilling in React happens when you need to pass data from a parent component to a deeply nested child component. To do this, you have to pass the data through all the components in between, even if they don’t actually need the data themselves.
Imagine you have a tree of components, and you want to pass some information from the top component all the way down to a component at the bottom. Instead of directly passing the data to the component that needs it, you have to pass it through each level of the tree, even if the intermediate components don’t use the data at all.
This can make the code more complicated and harder to understand. It can also be inefficient because unnecessary components have to receive and pass along the data.
To avoid prop drilling, you can use other techniques like React Context or state management libraries. These allow you to create a global state or store the data in a central place, so any component can access it directly without the need for prop drilling. This simplifies the code and makes it easier to manage the data flow.
Access Complete code : https://github.com/SiteJuggler/global-state-management-using-react-context-api
Create New React Project
create new React Project using create-react-app
Before creating a React.js project, ensure that you have Node.js and npm (Node Package Manager) installed on your system. You can download and install them from the official Node.js website: https://nodejs.org
Open a terminal or command line on your system. This is where you’ll run the necessary commands to create and manage your React.js project.
In the terminal, run the following command to install create-react-app
globally on your system:
npm install -g create-react-app
Navigate to the directory where you want to create your new React.js project. In the terminal, run the following command:

npx create-react-app first-app

Replace first-app
with the desired name of your project. This command will create a new directory named first-app
(or the name you provided) and set up a basic React.js project structure inside it.
React project is created, navigate to the project folder using the following command:
cd first-app
Run following command to run development server
npm start
Congratulations you successfully created React App.
Basic setup for Global state management using React Context API
Create a file called “GlobalState.js” and write the following code inside it.
import React, { createContext, useReducer } from "react";
import AppReducer from "./AppReducer";
const initialState = {
count: 0,
};
export const GlobalContext = createContext(initialState);
export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(AppReducer, initialState);
// Actions for changing state
function setCount(count) {
dispatch({
type: "SET_COUNT",
payload: count,
});
}
function increaseCount() {
dispatch({
type: "INCREASE_COUNT",
payload: 1,
});
}
function decreaseCount() {
dispatch({
type: "DECREASE_COUNT",
payload: 1,
});
}
return (
<GlobalContext.Provider
value={{
count: state.count,
setCount,
increaseCount,
decreaseCount,
}}
>
{children}
</GlobalContext.Provider>
);
};
In a React application, you often need to share data or state between different components. This code helps you achieve that by creating a “GlobalContext” which acts as a central storage for your application’s data.
First, we import the necessary tools from React. Then, we define an initial state object that represents the starting point for our data.
Next, we create the “GlobalProvider” component. This component will wrap around the rest of your application and make the global state accessible to all components within it.
Inside the “GlobalProvider” component, we use the useReducer hook. It allows us to manage state changes by specifying a reducer function that determines how the state is updated based on dispatched actions.
We define three action functions: setCount, increaseCount, and decreaseCount. These methods are used to update the state. For example, setCount allows you to set the count to a specific value, increaseCount increases the count by 1, and decreaseCount decreases the count by 1.
Finally, we render the “GlobalContext.Provider” component. It wraps around the children of the “GlobalProvider” component and provides them with access to the global state and action functions. The value prop of the provider specifies what data and functions are available to the components inside.
By using the “GlobalProvider” component and wrapping your application with it, you can access the global state and use the provided action functions to update it from any component within your application.
Create a file called “AppReducer.js” and write the following code inside it.
export default (state, action) => {
switch (action.type) {
case "SET_COUNT":
return { ...state, count: action.payload };
case "INCREASE_COUNT":
return { ...state, count: state.count + action.payload };
case "DECREASE_COUNT":
return { ...state, count: state.count - action.payload };
default:
return state;
}
};
The reducer function takes in two arguments: the current state and an action. It then checks the type of the action to determine what kind of state change needs to happen.
If the action type is “SET_COUNT”, it means we want to update the count to a specific value. The function creates a new state object by copying the existing state and changing the count property to the value provided in the action’s payload.
If the action type is “INCREASE_COUNT”, it means we want to add a certain value to the count. The function creates a new state object by copying the existing state and increasing the count property by the value in the action’s payload.
If the action type is “DECREASE_COUNT”, it means we want to subtract a certain value from the count. The function creates a new state object by copying the existing state and decreasing the count property by the value in the action’s payload.
If the action type doesn’t match any of the above cases, it means that no state change is needed. In this case, the function simply returns the current state without any modifications.
Once the reducer function determines the state changes, it returns the updated state.

This is minimum setup for state management using react context API
Next, we should import our provider in the main index.js file and wrap the components that we want to share global data with it.
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { GlobalContext, GlobalProvider } from "./GlobalState";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<GlobalProvider>
<GlobalContext.Consumer>{(context) => <App />}</GlobalContext.Consumer>
</GlobalProvider>
);
- Importing Dependencies:
- We import two important libraries: React and ReactDOM.
- React helps us build our React components, while ReactDOM helps us render them on the web page.
- We also import a CSS file named “index.css” for styling.
- Additionally, we import the “App” component from another file.
- Lastly, we import the “GlobalContext” and “GlobalProvider” from a file called “GlobalState”, which provides shared data for our app.
- Creating a Root Component:
- We create a special component using “ReactDOM.createRoot” method.
- This component represents the starting point of our app and specifies where it should be rendered on the web page.
- In this case, it looks for an element with the ID “root” in the HTML document.
- Rendering JSX:
- Inside the root component, we use the “root.render” method to render our React components.
- We wrap the “App” component with the “GlobalProvider” component to provide access to shared data.
- To access the shared data, we use the “GlobalContext.Consumer” component.
- Inside the consumer, we define a function that receives the shared data and renders the “App” component.
Next , Import Consumer component and wrap n
import React from "react";
import "./App.css";
import Child from "./Child";
import { GlobalContext } from "./GlobalState";
function App() {
return (
<GlobalContext.Consumer>
{(state) => (
<div className="App">
<h3 className="counter">{`Current Count : ${state.count}`}</h3>
<Child />
</div>
)}
</GlobalContext.Consumer>
);
}
export default App;
Next,
- Importing Dependencies:
- We import React, which is the library we use to build our React components.
- Additionally, we import a component called “Child” from another file.
- Finally, we import the “GlobalContext” from a file named “GlobalState”, which we assume holds some shared data.
- Defining the App Component:
- The “App” function represents the main component of our application.
- Inside this function, we define how our component should be rendered.
- Using Global Context:
- We use the “GlobalContext.Consumer” component to access the shared data provided by the “GlobalContext”.
- This consumer component wraps around our JSX code and allows us to use the shared data.
- Inside the consumer, we define a function that receives the shared state as an argument.
- Rendering JSX:
- Inside the function provided to the “GlobalContext.Consumer”, we return JSX code that represents the structure and content of our component.
- We have a div with a class name “App” that wraps the content of our component.
- Inside the div, we have an h3 element that displays the current count from the shared state.
- We use string interpolation to combine the count value with some text.
- Additionally, we render the “Child” component.
- Exporting the App Component:
- Finally, we export the “App” component as the default export of this file, which means it can be used in other parts of the application.
Next,
import React, { useContext } from "react";
import { GlobalContext } from "./GlobalState";
const Child = () => {
const { increaseCount, decreaseCount } = useContext(GlobalContext);
return (
<div>
<button onClick={increaseCount}>Increase Count</button>
<button onClick={increaseCount}>Increase Count</button>
</div>
);
};
export default Child;
- Importing Dependencies:
- The code starts by importing two important dependencies: React and useContext.
- React is the library we use to build our React components.
- useContext is a React hook that allows us to access the shared data from the “GlobalContext”.
- Importing GlobalContext:
- The code imports the “GlobalContext” from a file named “GlobalState”, which we assume holds the shared data and provides a context for it.
- Defining the Child Component:
- The “Child” component is defined as a functional component using an arrow function syntax.
- Inside this component, we define the rendering logic for the child component.
- Accessing Global Context:
- We use the “useContext” hook to access the shared data from the “GlobalContext”.
- We pass the “GlobalContext” as an argument to the “useContext” hook to indicate which context we want to access.
- The hook returns an object that contains the values provided by the “GlobalContext”, which we destructure into variables named “increaseCount” and “decreaseCount”.
- Rendering JSX:
- Inside the component, we return JSX code that represents the structure and content of the child component.
- We have a div that wraps two buttons.
- The first button has an onClick event handler that calls the “increaseCount” function when clicked.
- The second button also has an onClick event handler that calls the “increaseCount” function when clicked.
- Exporting the Child Component:
- Finally, the “Child” component is exported as the default export of this file, which means it can be imported and used in other parts of the application.
Output


Summary
Global state management with the React Context API allows us to share and manage data across different components in a React application. Here’s how it works:
Creating a shared data container:
We create a container to hold our shared data using the React Context API. Think of it as a central storage space for our data.
Wrapping components with a Provider:
We wrap the react components that need access to the global state data with a special component called the “Provider”.
The Provider component receives the shared data as a prop called “value”.
Inside the Provider component, we can define functions or values that can change or read the shared data.
Accessing shared data:
Components that need access to the shared data can use a component called the “Consumer”.
The Consumer component accepts a function as its child, which receives the shared data as an argument.
Inside this function, we can access the shared data and use it within our component.
Optional: Using the useContext hook:
Instead of using the Consumer component, we can also use a hook called “useContext” to access the shared data directly within functional components.
The useContext hook takes the shared data container as an argument and returns the shared data.
Updating the shared data:
To update the shared data, we modify it within the Provider component.
We can define functions or actions within the Provider component that modify the shared data.
Components that consume the shared data can call these functions or actions to update the shared data.
By using the React Context API for global state management, we can easily share and update data across different components in our application. It helps us avoid passing data through multiple levels of components (prop drilling) and provides a convenient way to access and update global state.
If you want to deploy react project on Amazon EC2 click here