Blog>
Snippets

State Management at Route Level

Provide an example of encapsulating local state within a route component, and how to fetch data upon entering a route using useEffect hook, ensuring the state is tightly coupled with the route lifecycle.
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';

function UserDetails() {
  const { userId } = useParams();
  const [userDetails, setUserDetails] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    setIsLoading(true);
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => {
        if (!response.ok) {
          throw new Error('Failed to fetch');
        }
        return response.json();
      })
      .then(data => setUserDetails(data))
      .catch(err => setError(err.toString()))
      .finally(() => setIsLoading(false));
  }, [userId]);

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h1>User Details</h1>
      {userDetails && <pre>{JSON.stringify(userDetails, null, 2)}</pre>}
    </div>
  );
}

export default UserDetails;
This code snippet demonstrates how to manage state within a route component in React. Here, `UserDetails` is a functional component that fetches and displays details of a user based on the `userId` obtained from the URL parameters using `useParams` hook from `react-router-dom`. `useState` is used to manage the user details data, loading state, and any potential errors. `useEffect` is hooked into the component's lifecycle to fetch data when the component mounts or when `userId` changes. The fetch request's loading state, response handling, and error handling are all encapsulated within this component, making the state management tightly coupled with the route's lifecycle.