React Router Pass Param to Component

ReactjsReact Router

Reactjs Problem Overview


const rootEl = document.getElementById('root');

ReactDOM.render(
    <BrowserRouter>
        <Switch>
            <Route exact path="/">
                <MasterPage />
            </Route>
            <Route exact path="/details/:id" >
                <DetailsPage />
            </Route>
        </Switch>
    </BrowserRouter>,
    rootEl
);

I am trying access the id in the DetailsPage component but it is not being accessible. I tried

<DetailsPage foo={this.props}/>

to pass parameters to the DetailsPage, but in vain.

export default class DetailsPage extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div className="page">
            <Header />
            <div id="mainContentContainer" >

            </div>
            </div>
    );
    }
}

So any idea how to pass the ID on to the DetailsPage ?

Reactjs Solutions


Solution 1 - Reactjs

I used this to access the ID in my component:

<Route path="/details/:id" component={DetailsPage}/>

And in the detail component:

export default class DetailsPage extends Component {
  render() {
    return(
      <div>
        <h2>{this.props.match.params.id}</h2>
      </div>
    )
  }
}

This will render any ID inside an h2, hope that helps someone.

Solution 2 - Reactjs

If you want to pass props to a component inside a route, the simplest way is by utilizing the render, like this:

<Route exact path="/details/:id" render={(props) => <DetailsPage globalStore={globalStore} {...props} /> } />

You can access the props inside the DetailPage using:

this.props.match
this.props.globalStore

The {...props} is needed to pass the original Route's props, otherwise you will only get this.props.globalStore inside the DetailPage.

Solution 3 - Reactjs

Since react-router v5.1 with hooks:

import { useParams } from 'react-router';

export default function DetailsPage() {
  const { id } = useParams();
}

See https://reacttraining.com/blog/react-router-v5-1/

Solution 4 - Reactjs

Use render method:

<Route exact path="/details/:id" render={(props) => (
    <DetailsPage id={props.match.params.id}/>
)} />

And you should be able to access the id using:

this.props.id

Inside the DetailsPage component

Solution 5 - Reactjs

In addition to Alexander Lunas answer ... If you want to add more than one argument just use:

<Route path="/details/:id/:title" component={DetailsPage}/>

export default class DetailsPage extends Component {
  render() {
    return(
      <div>
        <h2>{this.props.match.params.id}</h2>
        <h3>{this.props.match.params.title}</h3>
      </div>
    )
  }
}

Solution 6 - Reactjs

Use the component:

<Route exact path="/details/:id" component={DetailsPage} />

And you should be able to access the id using:

this.props.match.params.id

Inside the DetailsPage component

Solution 7 - Reactjs

Here's typescript version. works on "react-router-dom": "^4.3.1"

export const AppRouter: React.StatelessComponent = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route exact path="/problem/:problemId" render={props => <ProblemPage {...props.match.params} />} />
                <Route path="/" exact component={App} />
            </Switch>
        </BrowserRouter>
    );
};

and component

export class ProblemPage extends React.Component<ProblemRouteTokens> {

    public render(): JSX.Element {
        return <div>{this.props.problemId}</div>;
    }
}

where ProblemRouteTokens

> export interface ProblemRouteTokens { > problemId: string; }

Solution 8 - Reactjs

Another solution is to use a state and lifecycle hooks in the routed component and a search statement in the to property of the <Link /> component. The search parameters can later be accessed via new URLSearchParams();

<Link 
  key={id} 
  to={{
    pathname: this.props.match.url + '/' + foo,
    search: '?foo=' + foo
  }} />

<Route path="/details/:foo" component={DetailsPage}/>
    
export default class DetailsPage extends Component {

    state = {
        foo: ''
    }
    
    componentDidMount () {
        this.parseQueryParams();
    }

    componentDidUpdate() {
        this.parseQueryParams();
    }

    parseQueryParams () {
        const query = new URLSearchParams(this.props.location.search);
        for (let param of query.entries()) {
            if (this.state.foo!== param[1]) {
                this.setState({foo: param[1]});
            }
        }
    }

      render() {
        return(
          <div>
            <h2>{this.state.foo}</h2>
          </div>
        )
      }
    }

Solution 9 - Reactjs

This is for react-router-dom v6 (I highly suggest using functional components for this)

It's somewhat painful for react-router-dom to keep changing syntax and rules. But here goes nothing.

You can use both useParams and useSelector to solve this

import { useParams } from 'react-router';
import { useSelector } from 'react-redux';

const Component = () => {
const { id } = useParams();                              //returns the :id
const page = useSelector((state) => state.something[id]); //returns state of the page

return <div>Page Detail</div>;
}

export default Component;

BUT, the problem persist when you also have an action creator and you want to pass it as a props in connect function

export const connect(mapStateToProps, mapDispatchToProps)(Component)

since we are using useParams, it won't be passed to mapStateToProps that we created

const mapStateToProps = (state, ownProps) => {
console.log(ownProps)   //wont recognize :id
//hence
return {
  someReducers: state.someReducers[id] //would return an error: 'id' is not defined
 };
};

on the other hand, you can't entirely ignore the connect function since you need mapDispatchToProps to work with your component.

The workaround to this is to create a Higher Order Component withRouter function yourself. This was a deprecated react-router-dom helper.

//make this
import { useParams, useLocation, useNavigate } from 'react-router';
import { connect } from 'react-redux';
import { yourActionCreator } from '../actionCreator';

const withRouter = (Child) => {
return (props) => {
 const location = useLocation();
 const navigation = useNavigate();
 const params = useParams();
 return (
   <Child
   {...props}
   params={params}
   navigate={navigate}
   location={location}
   />
  );
 };
};

const Component = () => {
// your component...
return <div> Page Detail </div>
};

export mapStateToProps = (state, ownProps) => {
console.log(ownProps)     // would contain the :id params
return {
//something
 }
};

const mapDispatchToProps = {
yourActionCreator
}

export withRouter(connect(mapStateToProps, mapDispatchToProps)(Component));

Solution 10 - Reactjs

if you are using class component, you are most likely to use GSerjo suggestion. Pass in the params via <Route> props to your target component:

exact path="/problem/:problemId" render={props => <ProblemPage {...props.match.params} />}

Solution 11 - Reactjs

try this.

<Route exact path="/details/:id" render={(props)=>{return(
    <DetailsPage id={props.match.params.id}/>)
}} />

In details page try this...

this.props.id

Solution 12 - Reactjs

Simple example with Class, HoC and Router v5

package.json

"react-router-dom": "5.3.1",
"react-router": "5.3.1",
"@types/react-router-dom": "5.3.3",
// YourComponent.tsx

import React from 'react';
import { RouteComponentProps, withRouter } from 'react-router';

export interface PathParams {
    id: string;
}

export interface Props extends RouteComponentProps<PathParams> {}
export interface State {}

class YourComponent extends React.Component<Props, State> {
    constructor(props: Props) {
        super(props);
        this.state = {};

        console.log(props.match.params) // { id: 1 }
        // TypeScript completions
        console.log(props.match.params.id) // 1
    }

    render() {
        return <></>;
    }
}

export default withRouter(YourComponent);
// App.tsx

import './App.css';

import React from 'react';
import { Route, Switch, Router } from 'react-router-dom';

import YourComponent from './YourComponent';

function App(): JSX.Element {
    return (
        <Router>
            <Switch>
                <Route
                    path="/details/:id"
                    component={() => <YourComponent />}
                />
            </Switch>
        </Router>
    );
}

export default App;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionM TView Question on Stackoverflow
Solution 1 - ReactjsAlexander LunaView Answer on Stackoverflow
Solution 2 - ReactjsWinView Answer on Stackoverflow
Solution 3 - Reactjsuser1338062View Answer on Stackoverflow
Solution 4 - ReactjsSteven Daniel AndersonView Answer on Stackoverflow
Solution 5 - ReactjsManuelView Answer on Stackoverflow
Solution 6 - ReactjsDekelView Answer on Stackoverflow
Solution 7 - ReactjsGSerjoView Answer on Stackoverflow
Solution 8 - ReactjsManuelView Answer on Stackoverflow
Solution 9 - ReactjsdiazlpView Answer on Stackoverflow
Solution 10 - ReactjsMatteus BarbosaView Answer on Stackoverflow
Solution 11 - ReactjsAkshaj NairView Answer on Stackoverflow
Solution 12 - ReactjsFilip SemanView Answer on Stackoverflow