Search code examples
javascriptreactjsreact-hooksreact-routerreact-router-dom

I have a shopping app component that I only want to show on a particular page. Tried useLocation but the component has dynamic ids


I want to know how I can make my "page" variable in the below code dynamic, so I can properly compare it with the location.pathname variable which will have dynamic page ids.

import { useLocation } from 'react-router-dom';

function AddToCart() {
  function IsItemPage() {
    const page = '/item_page';
    const location = useLocation();
    console.log(location);
    if (location.pathname == page) {
      return true;
    };
  }

  return IsItemPage() && ( 
    <span className='add-to-cart'>
      <button>Add Item</button>
      <button>Cart</button>
    </span>
  );
}

export default AddToCart;

Now each item I open from the home page has a unique id for example: "/item_page/2" and obviously I cannot hard code it. If I provide the absolute path to the "page" variable like "/item_page/1" or something, the component is working as expected but only for that particular item with 'id: 1'. But I need to be able to achieve this for every item I open from the home page.

So how can I achieve this?


Solution

  • If you just want to check if the current URL path matches a specific path (or pattern) then you can use the useMatch hook, no need to re-invent the wheel.

    Example:

    useMatch("/item_page/:id?");
    

    This will match any "/item_page" and "/item_page/XYZ" sub-route path, returning a defined PathMatch object for matches, or null for non-matches.

    Code:

    import { useMatch } from "react-router-dom";
    
    function AddToCart() {
      const isItemPage = useMatch("/item_page/:id?");
    
      return (
        isItemPage && (
          <span className="add-to-cart">
            <button>Add Item</button>
            <button>Cart</button>
          </span>
        )
      );
    }
    
    export default AddToCart;
    

    Since it seems you want to render this AddToCart component with select routes, an alternative is to conditionally render it with the select routes via a layout route component. Layout routes are used to render common UI and apply common logic to a set of nested route components.

    Example:

    function AddToCart() {
      return (
        <span className="add-to-cart">
          <button>Add Item</button>
          <button>Cart</button>
        </span>
      );
    }
    
    import { Outlet } from "react-router-dom";
    
    const ItemPageLayout = () => {
      ...
      return (
        ...
        <Outlet />
        <AddToCart />
        ...
      );
    };
    
    <Routes>
      {/* Non-Item_page routes */}
      ...
    
      <Route path="item_page">
        <Route element={<ItemPageLayout />}>
          {/* Item pages with layout and AddToCart buttons */}
          <Route index element={<h1>Item Page</h1>} />
          <Route path=":id" element={<h1>Item Detail Page</h1>} />
          ...
        </Route>
    
        {/* Item pages without layout and no AddToCart buttons */}
        ...
      </Route>
    </Routes>