How to Use the React Context API in React Projects

React is a powerful JavaScript library for building user interfaces. In this blog post, we’ll explore how to create a master-detail page using the Fetch API for data fetching, React Context for state management, and TypeScript for static typing.

Understanding React Context

In React, Context is a mechanism that allows you to share values (like state or functions) between components without having to pass them explicitly through each level of the component tree. This can be particularly useful when dealing with deeply nested components or when certain values need to be accessible by multiple components.

Why Use Context?

Consider a scenario where multiple components in your application need access to the same data or functionality. Traditionally, you might pass this data down as props through each intermediate component, leading to a prop-drilling problem. Context provides an elegant solution to this problem by allowing you to establish a “global” state that can be consumed by any component in the tree without explicit prop passing.

Introducing Context in the Example

In the provided example, we used React Context to manage the selected user and the list of users. The UserContext file defines a UserProvider component that wraps its children with a context provider. This provider makes the context values (selected user, list of users, and related functions) accessible to any child component that subscribes to this context.

Step 1: Set Up React App with TypeScript

Start by creating a new React app with TypeScript using Create React App:

npx create-react-app user-management --template typescript
cd user-management

Step 2: Create UserContext

Create a UserContext.tsx file to manage the selected user state using React Context.

// UserContext.tsx
import React, { createContext, useState, ReactNode } from 'react';

interface User {
  id: number;
  name: string;
  email: string;
  // Add additional fields if needed
}

interface UserContextProps {
  selectedUser: number | null;
  selectUser: (userId: number) => void;
  users: User[];
  fetchUsers: () => Promise<void>;
}

export const UserContext = createContext<UserContextProps | undefined>(undefined);

interface UserProviderProps {
  children: ReactNode;
}

export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
  const [selectedUser, setSelectedUser] = useState<number | null>(null);
  const [users, setUsers] = useState<User[]>([]);

  const selectUser = (userId: number) => {
    setSelectedUser(userId);
  };

  const fetchUsers = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const data = await response.json();
      setUsers(data);
    } catch (error) {
      console.error('Error fetching users:', error);
    }
  };

  return (
    <UserContext.Provider value={{ selectedUser, selectUser, users, fetchUsers }}>
      {children}
    </UserContext.Provider>
  );
};

Consuming Context in Components Components such as UserList and UserDetails then consume this context using the useContext hook. This allows them to access and interact with the shared state without the need for prop drilling.

Step 3: Create UserList Component

Now, let’s create a UserList.tsx component to display the list of users.

// UserList.tsx
import React, { useContext, useEffect } from 'react';
import { UserContext } from './UserContext';

const UserList: React.FC = () => {
  const { users, selectUser, fetchUsers } = useContext(UserContext);

  useEffect(() => {
    fetchUsers();
  }, [fetchUsers]);

  return (
    <div>
      <h2>User List</h2>
      <ul>
        {users.map((user) => (
          <li key={user.id} onClick={() => selectUser(user.id)} style={{ cursor: 'pointer' }}>
            {user.name}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default UserList;

Step 4: Create UserDetails Component

Next, create a UserDetails.tsx component to display the details of the selected user.

// UserDetails.tsx
import React, { useContext, useEffect } from 'react';
import { UserContext } from './UserContext';

const UserDetails: React.FC = () => {
  const { selectedUser, users, fetchUsers } = useContext(UserContext);
  const user = users.find((user) => user.id === selectedUser);

  useEffect(() => {
    if (!user) {
      fetchUsers();
    }
  }, [user, fetchUsers]);

  if (!user) {
    return <p>Select a user from the list to view details.</p>;
  }

  return (
    <div>
      <h2>User Details</h2>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
      {/* Additional user details */}
    </div>
  );
};

export default UserDetails;

Step 5: Use Components in App.tsx

Now, integrate these components in the App.tsx file.

// App.tsx
import React from 'react';
import UserList from './UserList';
import UserDetails from './UserDetails';
import { UserProvider } from './UserContext';

const App: React.FC = () => {
  return (
    <UserProvider>
      <div>
        <h1>User Management App</h1>
        <UserList />
        <UserDetails />
      </div>
    </UserProvider>
  );
};

export default App;

Step 6: Run Your App

Start your React app:

npm start

Visit http://localhost:3000 in your browser. You should see a list of users on the left side. Clicking on a user will display their details on the right side.

Next Post Previous Post
No Comment
Add Comment
comment url