Context API Notes

Introduction

When working with React, you often need to share data between components. The traditional way of passing data is through props. However, as your application grows, passing data through multiple levels of components (called "prop drilling") can become cumbersome and error-prone. This is where Context API comes into play. Context API simplifies state management by allowing you to share state across your component tree without explicitly passing props at every level.

Key Points:

  • Props within props (prop drilling): Passing data through multiple layers of components is not directly possible without explicitly sending it as props.

  • Context API and State Management: Context API provides a straightforward way to manage state, but for more complex applications, tools like Redux, Redux Toolkit, or Zustand offer additional features for state management in an organized way.

  • Injecting Context: Context can be injected at any point in the component tree, giving flexibility in how and where it’s used.


Flow of Code

Here’s an example application demonstrating the use of Context API.

File Structure:

src/
 |-- components/
 |    |-- Login.jsx
 |    |-- Profile.jsx
 |-- context/
 |    |-- UserContextProvider.jsx
 |    |-- UserContext.js
 |-- App.jsx
 |-- App.css

App.jsx

This is the entry point of the application where the Context API is implemented.

import './App.css';
import Login from './components/Login';
import Profile from './components/Profile';
import UserContextProvider from './context/UserContextProvider';

function App() {
  // Context API is handled here
  return (
    <UserContextProvider>
      <h1>React with Chai</h1>
      <Login />
      <Profile />
    </UserContextProvider>
  );
}

export default App;

Explanation:

  • The UserContextProvider wraps the components Login and Profile. This means that both components will have access to the context data provided by UserContextProvider.

  • The <h1> tag is used for display purposes only.

  • Components Login and Profile demonstrate consuming the context.


context/UserContextProvider.jsx

So, UserContext is where the information is stored, and UserContextProvider is the helper that makes sure the information is available to everyone in the app!

This file defines the Context Provider, which wraps around the components that need access to the context data.

import React from 'react';
import UserContext from './UserContext';

// `children` works like a placeholder for nested components, similar to `div` or React Router's `Outlet`.
const UserContextProvider = ({ children }) => {
    // State managed within the context
    const [user, setUser] = React.useState(null);

    // `children` will be wrapped and rendered
    return (
        // Passing an object with `user` and `setUser` as the context value
        <UserContext.Provider value={{ user, setUser }}>
            {children}
        </UserContext.Provider>
    );
};

export default UserContextProvider;

Explanation:

  • React.useState is used to manage the user state within the provider.

  • UserContext.Provider wraps the children and provides the user state and setUser function to all components that consume the context.

  • The value prop of Provider is used to pass the state and functions.


context/UserContext.js

This file creates the context object.

import React from 'react';

// Creating the context
const UserContext = React.createContext();

// Exporting the context object
export default UserContext;

Explanation:

  • React.createContext creates a context object.

  • This context object can be used to share data across components.

  • When wrapped with a Provider, all components within the Provider's scope can access the data.


components/Login.jsx

This component collects user credentials and updates the context.

import React, { useContext, useState } from 'react';
import UserContext from '../context/UserContext';

const Login = () => {
    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");
    const { setUser } = useContext(UserContext);

    const handleSubmit = (e) => {
        // Prevent the default form submission
        e.preventDefault();
        // Update the context with the user data
        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;

Explanation:

  • Two states, username and password, are used to capture user inputs.

  • useContext fetches the setUser function from UserContext.

  • On submitting the form, the setUser function updates the context with the entered data.


components/Profile.jsx

This component displays the user data from the context.

import React, { useContext } from 'react';
import UserContext from '../context/UserContext';

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

    if (!user) {
        return (
            <div>
                Please login
            </div>
        );
    } else {
        return (
            <div>
                <h1>Welcome {user.username}</h1>
            </div>
        );
    }
};

export default Profile;

Explanation:

  • useContext fetches the user data from UserContext.

  • If user is not set, it prompts the user to log in.

  • If user is set, it displays a welcome message with the username.


Summary:

  1. Context API avoids the need for prop drilling by providing a way to share data between components directly.

  2. Login and Profile components demonstrate how to update and consume context data.

  3. It’s suitable for medium-sized applications.

Start using Context API today to simplify your state management journey!