Skip to main content

React Router URL Segments: Dynamic Routes, Search Params & Fragments

React Router - URL Segments

In this post, we'll dive into routing concepts like dynamic segments, optional segments and fragments (URL hashes), which are crucial when working with React Router.

Dynamic Segments

Dynamic segments are used to pass parameters in the URL, which are then accessible in your React components.

For instance, consider a scenario where you have a blog app, and each post has a unique ID. To access the details of a specific post, you can use dynamic segments in the route path:

import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Post from "./Post";

function App() {
return (
<Router>
<Routes>
<Route path="/post/:id" element={<Post />} />
</Routes>
</Router>
);
}

In the example above, :id is a dynamic segment. When a user navigates to /post/123, React Router will match the route and pass the id parameter to the Post component.

useParams

To access the dynamic parameter inside the Post component, we use the useParams hook:

import { useParams } from "react-router-dom";

function Post() {
const { id } = useParams(); // Get the dynamic segment (id)

return <div>Post ID: {id}</div>;
}

Splats

In React Router, splats (*) capture all remaining URL segments after a certain point. It's often used for wildcard routes or catch-all routes. For example, you could create a route that matches any URL that starts with /files:

<Route path="/files/*" element={<Files />} />

Here, * will capture everything after /files, so if the user visits /files/documents/notes, the Files component will render with the appropriate logic to handle the URL.

To get the splat value inside a component, you can use the useParams hook:

import { useParams } from "react-router-dom";

function Files() {
const { "*": remainingPath } = useParams(); // Get the splat (remaining path)

return <div>Remaining Path: {remainingPath}</div>;
}

If the user visits /files/documents/notes, remainingPath will be documents/notes.


Search Parameters

Search parameters (query strings) are the part of the URL that comes after the ?, often used to pass dynamic data like filters, page numbers, or user preferences.

/products?category=shoes&page=2

useSearchParams

You can access the query parameters using the useSearchParams hook, which gives you a way to read and manipulate the query string.

  1. How to Access Search Parameters

    import { useSearchParams } from "react-router-dom";

    function ProductList() {
    const [searchParams] = useSearchParams();

    const category = searchParams.get("category");
    const page = searchParams.get("page");

    return (
    <div>
    <h2>Category: {category}</h2>
    <p>Page: {page}</p>
    </div>
    );
    }
  2. Setting or Updating Search Parameters

    import { useSearchParams } from "react-router-dom";

    function FilterButtons() {
    const [searchParams, setSearchParams] = useSearchParams();

    const handleClick = () => {
    setSearchParams({ category: "shoes", page: "1" });
    };

    return <button onClick={handleClick}>Filter Shoes</button>;
    }
  3. Preserve Existing Params While Updating

    setSearchParams((prev) => {
    prev.set("sort", "price");
    return prev;
    });

Fragments (URL Hashes)

Fragments (or URL hashes) are the part of a URL that comes after #.

They are useful for navigating to specific sections of a page, such as when you want to link directly to a specific section of an article.

useLocation

You can use the useLocation hook from React Router to read the fragment (hash) part of the URL:

import { useLocation } from "react-router-dom";
import { useEffect } from "react";

function About() {
const location = useLocation();

useEffect(() => {
if (location.hash) {
const element = document.getElementById(location.hash.substring(1));
if (element) {
element.scrollIntoView({ behavior: "smooth" });
}
}
}, [location.hash]);

return (
<div>
<h2>About Page</h2>
<div id="contact">Contact Section</div>
</div>
);
}