Search code examples
javascriptreactjsreact-router-dom

React not rendering component when changing routes


I have a page with products. My problem is that when I try to click on a product, the url is changing, but nothing renders on the screen. It still shows the component where all the products are rendered.

I tried couple of different things, but nothing seemed to work

<Route path="store" element={<Store />}>
  <Route path="protein" element={<Products />} />
  <Route path="protein/*" element={<SingleProduct />} />
</Route>

I also tried with:

<Route path="store" element={<Store />}>
  <Route path="protein" element={<Products />}>
    <Route path="*" element={<SingleProduct />} />
  </Route>
</Route>

Also with:

<Route path="/store/protein/*" element={<SingleProduct />} />

So that it is not a child route.

But that also didn't work. Any ideas what I'm doing wrong?

Edit: That is my Store component :

import React from "react";
import SidePanel from "../components/storeComponents/SidePanel";
import Products from "../components/storeComponents/Products";
import "./Store.css";

const Store = () => {
  return (
    <div className="store-page">
      <SidePanel />
      <Products />
    </div>
  );
};

export default Store;

Solution

  • Trailing path splats are used when the routed component is rendering descendent routes, e.g. if SingleProduct rendered another Routes and set of Route components, the trailing "*" allows these routes to also be matched. You are trying to use nested routes though.

    The Store component is just rendering the Products component directly. It should instead render an Outlet component for the nested routes to render out their content.

    import { Outlet } from 'react-router-dom';
    
    const Store = () => {
      return (
        <div className="store-page">
          <SidePanel />
          <Outlet />
        </div>
      );
    };
    

    You are also rendering Products and SingleProduct on the same route path. You likely want to render SingleProduct on a sub-route path with a dynamic path segment, e.g. something like "protein/:productId".

    <Route path="store" element={<Store />}>
      <Route path="protein" element={<Products />} />
      <Route path="protein/:productId" element={<SingleProduct />} />
    </Route>
    

    Ensure that the Products component is correctly linking to a valid "/store/protein/:productId" path. Examples:

    Absolute path from root "/":

    <Link to={`/store/protein/${product.id}`}>
      {product.title}
    </Link>
    

    Relative path from products page "/store/protein":

    <Link to={product.id}> // <-- no leading slash "/" character
      {product.title}
    </Link>