2

I want to build a page when from list of products I want to see product by ID. In my App file I have something like that:

<Route path={ROUTES.product} element={<Product id={1} />}> 

but I want to replace static id with the value that comes from the selected product. In my Product file I have redirection to page with product but I don't know how I can pass the ID.

onClick={() => { navigate(`/products/${product?.id}`)}}

Any help would be appreciated.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
hello world
  • 23
  • 1
  • 1
  • 5

3 Answers3

4

The code you've provided appears to pass the id value in the path. It seems your question more about getting the Product component to have the correct id prop passed to it.

Given: path is "/products/:id"

Options to access the id param:

  1. Use the useParams hook in Product to read the id route path param. This only works if Product is a function component.

    import { useParams } from 'react-router-dom';
    
    ...
    
    const { id } = useParams();
    

    ...

    <Route path={ROUTES.product} element={<Product />} />
    
  2. Use a wrapper component to use the useParams hook and inject the id value as a prop. This is useful if Product is not a function component.

    import { useParams } from 'react-router-dom';
    
    const ProductWrapper = () = {
      const { id } = useParams();
      return <Product id={id} />
    };
    

    ...

    <Route path={ROUTES.product} element={<ProductWrapper />} /> 
    
  3. Create a custom withRouter Higher Order Component to use the useParams hook and inject a params prop.

    import { useParams, ...other hooks... } from 'react-router-dom';
    
    const withRouter = Component => props => {
      const params = useParams();
      ... other hooks...
      return (
        <Component
          {...props}
          params={params}
          ... other hooks ...
        />
      );
    };
    

    ...

    Wrap Product with withRouter HOC and access id param from props.params

    props.params.id // or this.props.params
    
    ...
    
    export default withRouter(Product);    
    

    ...

    <Route path={ROUTES.product} element={<Product />} />
    
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • I have a question to your answer: when I try to pass id in Route component `}> ` I get an error: Type 'string | undefined' is not assignable to type 'number'. When in my Product file I have something like this: `type Props = { ProductID: number; }; const ProductDetailsView = ({ ProductID }: Props) => { const [products, setProduct] = useState(); const { id } = useParams();` – hello world Apr 25 '22 at 20:05
  • @helloworld All route params will be of type String. If using any params for assignment to local variables/etc... they need to be converted to the correct matching types, for example, if all `id` values are numbers, use `productId={Number(id)}`. Or you can amend your type declaration to include sting types, i.e. `type props = { productId: number | string | null; };`. Does this make sense? – Drew Reese Apr 25 '22 at 20:07
  • @helloworld Sorry, I'm no Typescript expert, but it might be `type props = { productId?: number | string; };` for optional props. Not sure if you still need `null` in there though. – Drew Reese Apr 25 '22 at 20:15
  • @helloworld Oh, and sorry it it wasn't clear, all of the options I've presented remove sending any props at the route level, they each use the `useParams` hook to get the value, so the route doesn't pass anything additional to the component it's rendering. – Drew Reese Apr 25 '22 at 20:16
  • Thank You, it makes more sense now. But I have additionaly one more question because as I can see the value that is passed to the backend is NaN. Do you know how I can resolve this problem? – hello world Apr 25 '22 at 20:41
  • @helloworld For this I think we'd need to see this `Product` component code ***and*** the product data being iterated and passing a value here `navigate(\`/products/${product?.id}\`)` to say why any value is `NaN` other than whatever you are converting *isn't* actually a number. – Drew Reese Apr 25 '22 at 20:44
  • @helloworld Sorry, how is that question different from this one? It looks like the same exact issue of getting the `id` from the URL path. Am I misunderstanding something? – Drew Reese Apr 25 '22 at 21:17
  • I belive You are understanding it correctly and the problem is still with passing the `id` value. But I have no idea how to resolve this problem still. – hello world Apr 25 '22 at 21:21
  • @helloworld I think if you've implemented the solutions above though, you won't need to pass a prop at the route level `` as the wrapper/HOC/hook would have already accessed the `id` from the path directly or passed as a prop to the underlying component using it. – Drew Reese Apr 25 '22 at 22:24
0

so you already have the id with this

navigate(`/products/${product?.id}`)

just in Product component you can access id with

 const { id } = useParams();

if you need to pass extra data you can try:

navigate(`/product/${product?.id}`, { state: { someExtradata }};

that you can access state in the component with :

 const { state } = useLocation();
Hesam
  • 450
  • 2
  • 11
  • Do I need a Route component to redirect to page with product details? – hello world Apr 25 '22 at 19:09
  • it depends on your routing and product structure, but commonly yes. – Hesam Apr 25 '22 at 19:12
  • Please correct me if I'm wrong, I can access id in such way in my App file: `}> `? – hello world Apr 25 '22 at 19:16
  • no you just need to pass ProductDetailsView component in element and dose not needs pass id. then you will navigate to the product with `/products/${product?.id}`. In productDetailsView component you can access id from browser route with useParams. – Hesam Apr 25 '22 at 19:23
  • accutly you have to get the id from route not pass it as props. – Hesam Apr 25 '22 at 19:25
  • When I try to do something like this: `}> ` I'm getting an error that property id is missing. And when commenting out this Router section I'm getting blank page. – hello world Apr 25 '22 at 19:30
  • How can I get id from route? – hello world Apr 25 '22 at 19:34
  • it is probably because of you ProductDetauksView accept id as props. so you need to remove the id props and get the id from useParams. check this https://reactrouter.com/docs/en/v6/getting-started/overview#reading-url-parameters – Hesam Apr 25 '22 at 19:35
-1
onClick={ () => Navegar(id) }
function Navegar(id) {
    navigate('/products/id)
}
karel
  • 5,489
  • 46
  • 45
  • 50
Juan
  • 57
  • 1
  • 5
  • [A code-only answer is not high quality](//meta.stackoverflow.com/questions/392712/explaining-entirely-code-based-answers). While this code may be useful, you can improve it by saying why it works, how it works, when it should be used, and what its limitations are. Please [edit] your answer to include explanation and link to relevant documentation. – Stephen Ostermiller Apr 27 '22 at 09:58