30

I have problem passing id to my page with product, I tried everything and search answer but it still doesn't work.

Here is my index.js:

import React from "react";
import {render} from "react-dom";
import {Router, Route, IndexRoute, hashHistory} from "react-router";

import {Menu} from './components/Menu';
import {MainPage} from './components/MainPage';
import {DetailsProduct} from './components/DetailsProduct';

class App extends React.Component{

    render(){
        return(
        <Router history={hashHistory}>
            {/* <IndexRoute component={Menu}></IndexRoute> */}
            <Route path="/" component={()=>(<div><Menu/><MainPage/></div>)}></Route>
            <Route path={"product/:id"} component={()=>(<div><Menu/><DetailsProduct>asd</DetailsProduct></div>)}></Route>
        </Router>
        )
    }
}

render(<App/>, window.document.getElementById("app"));

And DetailsProduct (page: http://localhost:8080/#/product/1)

import React from "react";    
export class DetailsProduct extends React.Component{

    render(){
        console.log(this.props.params); <-- this is undefined

        return(
            <h1>Product</h1>
        )
    }
}

I came back here after a 3 years. Solution:

Rendering components in this way is not a good solution:

<Route path={"product/:id"} component={()=>(<div><Menu/><DetailsProduct>asd</DetailsProduct></div>)}></Route>

But if you want to render a component like this (which I do not recommend) you have to add props as param argument to the function and then make restructuring on the component in which you want that props({...props})

<Route path={"product/:id"} component={(props)=>(<div><Menu/><DetailsProduct>asd</DetailsProduct></div>)}></Route>

Best solution is render route like this:

<Route path={"product/:id"} component={DetailsProduct}></Route>

and inside DetailsProduct you can render <Menu /> or use Switch :

<Menu/>
<Switch>
    <Route exact path={"product/:id"} component={DetailsProduct}/>
    // Add any other routes you want here
</Switch>
Paweł Baca
  • 814
  • 2
  • 15
  • 28

10 Answers10

25

I was also getting the same problem when I used this.props.params.id.

But when i tried to put console.log(this.props) in the component where I'm passing the id, it shows my id in match object so use:

this.props.match.params.id

to get the id (notice the added match).

vmarquet
  • 2,384
  • 3
  • 25
  • 39
rajat
  • 251
  • 2
  • 4
24

For me I was using the render method and finding that this.props.match was undefined in rendered components. This was the solution for me, you have to pass in props.

this.props.match will be undefined for:

<Route path='/users/:id' render={() => <UserDetail/>}/>

Do this instead:

<Route path='/users/:id' render={(props) => <UserDetail {...props}/>}/>

https://reacttraining.com/react-router/web/api/Route/render-func

Glen Thompson
  • 9,071
  • 4
  • 54
  • 50
14

replace this :

<Route path={"product/:id"} component={()=>(<div><Menu/><DetailsProduct>asd</DetailsProduct></div>)}></Route>

with :

<Route path={"product/:id"} component={DetailsProduct}></Route>
Fawaz
  • 3,404
  • 3
  • 17
  • 22
4

in react-router-dom v6 you have to use useParams().

like this:

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

const { id } = useParams();

this way you can access the id

3

react router new version changed the route props object as the following: this.props.match.params instead this.props.params

https://reacttraining.com/react-router/web/api/match

3

In the new version you have to use

useParams()

instead

this.props.params
taha
  • 53
  • 4
0

I assume you are not using react-router v4 but either v2.x.x or v3.x.x. In that case you should restructure your routes and you can pass multiple component using the components props as

   <Router history={hashHistory}>
        <Route path="/" component={Layout}>
              <IndexRoute components={{menu: Menu, mainPage: MainPage}}/>
              <Route path={"product/:id"} component={{menu: Menu, detail: DetailsProduct}}/>
         </Route>
    </Router>

And in the Menu Component Also the way you want it work is relatively very easy to do using react-router v4. In that case you can make use of prop render to provide a component and you could do the following with it

import {HashRouter as Router, Route} from 'react-router-dom';
...
<Router>
    <Route path="/" render={()=>(<div><Menu/><MainPage/></div>)}></Route>
    <Route path={"product/:id"} render={()=>(<div><Menu/><DetailsProduct>asd</DetailsProduct></div>)}></Route>
</Router>
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
0

I use

import { Router, Route, browserHistory, IndexRoute} from 'react-router'

and

import {syncHistoryWithStore, routerReducer} from 'react-router-redux'

then I can get id by this.props.params.id

Paweł Baca
  • 814
  • 2
  • 15
  • 28
0

I had the same issue when I had this code

<Route
    path={"/:url"}
    render={(routerProps) =>
        <BusinessApps
            {...routerProps}
            {...this.props}
            size={size}
        />
    }/>

I removed {...this.props} to fix the issue.

nomadus
  • 859
  • 1
  • 12
  • 28
0

In React 6, you need to useParams like the following code when you pass it as a class-base:

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

and for export write this:

export default (props) => (
<App
    {...props}
    params={useParams()}
/>

)

Finally you can use the params:

console.log(this.props.params);