When building modern React applications, managing state efficiently across multiple components can become challenging. Prop drilling — passing data through several layers of components — can make your code harder to maintain and debug. Fortunately, React provides a built-in solution: the Context API. Combined with the useContext hook, it offers a clean and powerful way to share state globally without third-party libraries like Redux. In this tutorial, we will see how we can useContext to Share State Between Components.


Setting up a React App

Let’s start by creating a new React project. You can use either Vite or Create React App — both are great for beginners.

Using Create React App
npx create-react-app react-context-demo
cd react-context-demo
npm start
Bash
Using Vite (faster alternative)
npm create vite@latest react-context-demo --template react
cd react-context-demo
npm install
npm run dev
Bash

Once your app is running, you should see the default React starter page at http://localhost:3000 or http://localhost:5173.

useContext to Share State Between Components


Understanding the Context API

Before diving into code, let’s break down the Context API.

  • React.createContext() – Creates a Context object that can hold and provide data.
  • Context.Provider – Wraps part of your app and provides the data to all children.
  • useContext(Context) – A React hook that allows child components to consume the data directly.

This trio allows you to share state globally without passing props manually at every level.


Creating a Context

Let’s create a new file called AppContext.js inside the src folder.

// src/AppContext.js
import { createContext, useState } from "react";

export const AppContext = createContext();

export const AppProvider = ({ children }) => {
  const [user, setUser] = useState("Guest");

  const login = (name) => setUser(name);
  const logout = () => setUser("Guest");

  return (
    <AppContext.Provider value={{ user, login, logout }}>
      {children}
    </AppContext.Provider>
  );
};
JavaScript
What’s happening here:
  • We create a new context (AppContext).
  • Define a user state and functions to log in or log out.
  • Wrap children components with AppContext.Provider to make data available anywhere inside the tree.

Wrapping the App with the Provider

Open src/main.jsx (or index.js if using Create React App) and wrap your main <App /> component with the AppProvider.

// src/main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import { AppProvider } from "./AppContext";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <AppProvider>
      <App />
    </AppProvider>
  </React.StrictMode>
);
JavaScript

Now every component inside App has access to the context.


Consuming Context with useContext

Let’s use the shared user state in two components — one to display the current user, and another to log in/out.

UserProfile.jsx
import { useContext } from "react";
import { AppContext } from "./AppContext";

export const UserProfile = () => {
  const { user } = useContext(AppContext);
  return <h2>Welcome, {user}!</h2>;
};
JavaScript
LoginPanel.jsx
import { useContext, useState } from "react";
import { AppContext } from "./AppContext";

export const LoginPanel = () => {
  const { login, logout, user } = useContext(AppContext);
  const [name, setName] = useState("");

  return (
    <div>
      <input
        type="text"
        placeholder="Enter your name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <button onClick={() => login(name)}>Login</button>
      <button onClick={logout}>Logout</button>
      <p>Current User: {user}</p>
    </div>
  );
};
JavaScript
Using in App.jsx
import { UserProfile } from "./UserProfile";
import { LoginPanel } from "./LoginPanel";

function App() {
  return (
    <div style={{ textAlign: "center", marginTop: "2rem" }}>
      <h1>React Context API Example</h1>
      <UserProfile />
      <LoginPanel />
    </div>
  );
}

export default App;
JavaScript

Now, when you type your name and click Login, every component consuming AppContext will update instantly — no prop drilling required!


Benefits of useContext

Using useContext and the Context API offers several benefits:

No prop drilling – Pass data directly to any component and I can attest to this being the biggest benefit of this, as for my day job I work on an app which has a lot of prop drilling.
Cleaner structure – Keep shared state logic in one place.
Lightweight alternative – Simpler than Redux or Zustand for small-to-medium apps.
Easy testing and scalability – Wrap only parts of the app that need shared state.


Best Practices

To get the most out of Context API:

  • Keep contexts focused — don’t store too much unrelated data in one context.
  • Combine Context API with custom hooks for cleaner logic.

Conclusion

You’ve just built a fully functional React app that uses the Context API and useContext hook to share state between components — without prop drilling or extra dependencies.

This pattern is perfect for:

  • User authentication
  • Theme toggling (light/dark)
  • Language/localization
  • Global UI state (modals, alerts, etc.)

By mastering useContext, you’ll write cleaner, more scalable React code that’s easy to understand and maintain.

If you find any of my posts useful and want to support me, you can buy me a coffee 🙂

https://www.buymeacoffee.com/bhumansoni

While you are here, maybe try one of my apps for the iPhone.

Products – My Day To-Do (mydaytodo.com)

Here are some of my other bloposts on Java

How to build a full stack Spring boot API with ReactJS frontend – My Day To-Do (mydaytodo.com)

How to call REST API with WebClient – My Day To-Do (mydaytodo.com)

How to build a jokes client in Java Spring Boot with RestTemplate – My Day To-Do (mydaytodo.com)

Have a read of some of my other posts on AWS

Upload to AWS S3 bucket from Java Spring Boot app – My Day To-Do (mydaytodo.com)

Deploy NodeJS, Typescript app on AWS Elastic beanstalk – (mydaytodo.com)

How to deploy spring boot app to AWS & serve via https – My Day To-Do (mydaytodo.com)


0 Comments

Leave a Reply

Verified by MonsterInsights