Search code examples
javascriptreactjsreact-routerreact-router-domnested-routes

React routing based on id


I work with react-router v6. I want to create a new route based on an id. On my homepage "example.com" I have a selection of articles. I want to create a detail view for each article "example.com/{id}". My approach looks like this:

App.tsx

import {
  BrowserRouter,
  Routes,
  Route,
} from "react-router-dom";
import ProjectWrapper from "./components/ProjectWrapper";
import Home from "./pages/Home";
import PageError from "./pages/PageError";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} >
          <Route path=":id" element={<ProjectWrapper />} />
        </Route>
        <Route path="*" element={<PageError />} />
      </Routes>
    </BrowserRouter>
  );
}

ProjectWrapper.tsx

import { useParams } from "react-router-dom";
import { ProjectList } from "../pages/algorithms/ProjectList";
import PageError from "../pages/PageError";

function ProjectWrapper() {
  const { id } = useParams();
  const project = ProjectList.find((project) => project.id.toLowerCase() === id?.toLowerCase());
 
  if (project === undefined) return (<PageError />);
 
  return (
    <div>
      {project!.shortDescription} 
    </div>
  )
}

export default ProjectWrapper;

Am I missing something ?


Solution

  • With the given routing code:

    <Routes>
      <Route path="/" element={<Home />} >
        <Route path=":id" element={<ProjectWrapper />} />
      </Route>
      <Route path="*" element={<PageError />} />
    </Routes>
    

    Home is what is called a Layout Route. Layout routes render some common logic and UI, and an Outlet component for nested Routes to render their content when matched.

    Example:

    import { ..., Outlet } from 'react-router-dom';
    
    const Home = () => {
      ...
    
      return (
        <>
          ...
    
          <Outlet /> // <-- nested routes render content here
        </>
      );
    };
    

    If you don't want the Home component to render along with children routes then place it on its own route.

    Examples:

    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/:id" element={<ProjectWrapper />} />
      <Route path="*" element={<PageError />} />
    </Routes>
    

    or

    <Routes>
      <Route path="/">
        <Route index element={<Home />} />
        <Route path=":id" element={<ProjectWrapper />} />
      </Route>
      <Route path="*" element={<PageError />} />
    </Routes>