React Context API

React Context API

Understanding the React Context API

React, one of the most popular JavaScript libraries for building user interfaces is known for its component-based architecture. However, as applications grow in complexity, managing state across components can become a daunting task. This is where the React Context API comes into play, offering a powerful solution to share data and state between components without the hassle of prop drilling.

The State Management Challenge

As React developers, we often find ourselves passing data from a parent component to a deeply nested child component through a series of props. This practice, known as prop drilling, can quickly lead to a spaghetti-like code structure, making maintenance and debugging a nightmare.

The React Context API addresses this issue by providing a way to share data or state across the component tree, making it accessible to any component without explicitly passing it through props.

What is the React Context API?

The React Context API is a feature that allows us to create, provide, and consume context. Context is a way to share values like data, functions, or theme settings between components without having to explicitly pass them through the component tree.

How to use React Context API?

Creating a Context

To start using the React Context API, we need to create a context using the createContext method:

// src/context/UserContext.js
import { createContext } from "react";

const UserContext = createContext();

export default UserContext;

This creates a context object with two components: Provider and Consumer.

Using the Provider

The Provider component is responsible for wrapping the part of the component tree where we want to make the context data available. It accepts a value prop, which holds the data we want to share:

// src/context/MyContextProvider.jsx
import React, { useState } from "react";
import UserContext from "./UserContext";

const UserContextProvider = ({ children }) => {
  const [user, setUser] = useState(null);

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
};

export default UserContextProvider;

Wrap the main element/app component with UserContextProvider

Wrap all the components that will be using the Provider or the main App component

// src/App.jsx
import "./App.css";
import Login from "./components/Login";
import Profile from "./components/Profile";
import UserContextProvider from "./context/UserContextProvider";

function App() {
  return (
    <UserContextProvider>
      <h1>React context</h1>
      <Login />
      <Profile />
    </UserContextProvider>
  );
}

export default App;
// src/components/Login.jsx
import React, { useState, useContext } from "react";
import UserContext from "../context/UserContext";

function Login() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  const { setUser } = useContext(UserContext);

  const handleSubmit = (e) => {
    e.preventDefault();
    setUser({ username, password });
  };
  return (
    <div>
      <h2>Login</h2>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="username"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="password"
      />
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
}

export default Login;
// src/components/Profile.jsx
import React, { useContext } from "react";
import UserContext from "../context/UserContext";

function Profile() {
  const { user } = useContext(UserContext);

  if (!user) return <div>Please login</div>;

  return <div>Welcome {user.username}</div>;
}

export default Profile;

Conclusion

The React Context API is a powerful tool that simplifies state management in React applications. By understanding how to create and use contexts, we can improve code maintainability and reduce the complexity of passing data through props. This allows us to focus on building robust and scalable applications without the hassle of prop drilling.