Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 51

Accessing URL Parameters with `useParams`

Recommended resources

Hello! Welcome back to our series on React Router.

In the last lesson, we successfully set up dynamic routes for our product pages. We created links that navigate to URLs like /products/1 and /products/2, and we configured a <Route> with the path /products/:productId to render our ProductDetailPage component for any of those URLs. However, that page is still just a static placeholder.

Today, we will make that page truly dynamic. You will learn how to access the value from the URL (like the 1 in /products/1) from within your React component. The key to this is a React Router hook called useParams.

This process is the client-side equivalent of what you might do in a Laravel controller. Where in Laravel you would capture a route parameter like {id} and pass it to your controller method, in React you will use useParams to pull productId directly from the URL into your component.

1. Introducing the useParams Hook

The useParams hook is provided by react-router-dom and is your tool for reading dynamic parameters from the URL. When you have a route defined with a parameter like <Route path="/products/:productId" ... />, calling useParams() inside the component rendered by that route will return an object containing the parsed URL parameters.

For the URL /products/123, useParams() would return an object like this: { productId: '123' }. Notice that the key, productId, matches the name we used in our route definition (:productId).

To see this in action, let's watch a short video that clearly demonstrates how to implement and use this hook.

React Router in Depth #7 - Route Parameters

The following video from the Net Ninja channel provides a great walkthrough of route parameters and the useParams hook. It will reinforce the concept and show you exactly how to access the dynamic ID in a component.

Please watch the following parts: What are Route Parameters? (00:00 - 01:03): This is a quick conceptual overview. Using useParams (01:46 - 03:18): This is the core section. Pay close attention to how useParams is imported and used with destructuring to get the id from the URL, and then how that id is displayed in the component.


2. Making the Product Detail Page Dynamic

Now that you've seen how useParams works, let's apply it to our ProductDetailPage component. We'll use the productId from the URL to find the correct product in our productData array and display its details.

Step 1: Update ProductDetailPage.jsx

Open your src/pages/ProductDetailPage.jsx file and modify it to look like this:

// src/pages/ProductDetailPage.jsx
import React from 'react';
import { useParams } from 'react-router-dom'; // 1. Import useParams
import { productData } from '../data';      // 2. Import our mock data

const ProductDetailPage = () => {
  // 3. Get the productId from the URL
  const { productId } = useParams();

  // 4. Find the product that matches the productId
  // Note: The param from the URL is a string, but our product.id is a number.
  // We use parseInt() to convert the string to a number for a correct comparison.
  const product = productData.find(p => p.id === parseInt(productId));

  // 5. Handle the case where the product isn't found
  if (!product) {
    return (
      <div>
        <h2>Product Not Found</h2>
        <p>Sorry, we couldn't find a product with that ID.</p>
      </div>
    );
  }

  // 6. Render the details of the found product
  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.description}</p>
      <p><strong>Status:</strong> {product.status}</p>
    </div>
  );
};

export default ProductDetailPage;

Let's break down the changes:

  1. Import useParams: We import the hook from react-router-dom.
  2. Import productData: We need access to our array of products to find the correct one.
  3. Call useParams: We call the hook and use object destructuring to extract the productId parameter. The name productId must exactly match the parameter name in your route path (/products/:productId).
  4. Find the Product: We use the find array method to search productData. This is a great example of combining modern array methods with React. A crucial detail here is parseInt(productId). URL parameters are always strings, but the IDs in our data are numbers. parseInt ensures we are comparing values of the same type (number === number).
  5. Handle "Not Found": It's good practice to handle cases where no matching product is found (e.g., if a user navigates to /products/99). We return a simple "not found" message.
  6. Render Product Details: If a product is found, we display its specific name, description, and status.

Now, run your application. Go to the /products page and click on the different product links. You should now see each product's unique details rendered on its own page!


Conclusion

Excellent work today! You have now connected all the pieces of dynamic routing. You can create a link to a dynamic URL, define a route to handle it, and use the useParams hook to fetch data from the URL and render a component with specific content.

Key Takeaways:

  • The useParams hook from react-router-dom returns an object of URL parameters.
  • The keys in the returned object match the parameter names defined in your <Route> path (e.g., :productId becomes productId).
  • URL parameters are always strings, so you may need to convert them (e.g., using parseInt()) before comparing them to other data types like numbers.
  • You can use the parameter to fetch data or find an item in an array to render a dynamic view.

Preview of the Next Lesson:
Our routes are working, but you might have noticed some repetition. For example, if we wanted a consistent layout (like a "Back to Products" link) on both the main products page and the detail page, we'd have to add it to both components. In the next lesson, we will explore nested routes and the <Outlet /> component, which provide a powerful way to create shared layouts for a group of related routes.