21

I'm using React Router to create a multi page app. My main component is <App/> and it renders all of the routing to to child components. I'm trying to pass props via the route, and based on some research I did, the most common way for child components to tap into props passed down is via the this.props.route object that they inherit. However, this object is undefined for me. On my render() function in the child component, I console.log(this.props) and am return an object that looks like this

{match: Object, location: Object, history: Object, staticContext: undefined}

Doesn't look like the props I expected at all. Here is my code in detail.

Parent Component (I'm trying to pass the word "hi" down as a prop called "test" in all of my child components):

import { BrowserRouter as Router, HashRouter, Route, Switch } from 'react-router-dom';
import Link from 'react-router';
import React from 'react';

import Home from './Home.jsx';
import Nav from './Nav.jsx';
import Progress from './Progress.jsx';
import Test from './Test.jsx';



export default class App extends React.Component {

  constructor() {
    super();

    this._fetchPuzzle = this._fetchPuzzle.bind(this);
  }

  render() {
    return (
      <Router>
        <div>
          <Nav />
          <Switch>
            <Route path="/" exact test="hi" component={Home} />
            <Route path="/progress" test="hi" component={Progress} />             
            <Route path="/test" test="hi" component={Test} />
            <Route render={() => <p>Page not found!</p>} />
          </Switch>
        </div>
      </Router>
    );
  }
}

Child:

import React from 'react';
const CodeMirror = require('react-codemirror');
import { Link } from 'react-router-dom';

require('codemirror/mode/javascript/javascript')

require('codemirror/mode/xml/xml');
require('codemirror/mode/markdown/markdown');

export default class Home extends React.Component {

  constructor(props) {
    super(props);

    console.log(props)

  }

  render() {
    const options = {
      lineNumbers: true,  
      theme: 'abcdef'    
      // mode: this.state.mode
    };
    console.log(this.props)

    return (
      <div>
        <h1>First page bro</h1>        
        <CodeMirror value='code lol' onChange={()=>'do something'} options={options} />
      </div>);
  }
}

I'm pretty new to React so my apologies if I'm missing something obvious. Thanks!

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
Mark Romano
  • 701
  • 3
  • 12
  • 25
  • 1
    What information do you want to extract from the `route` object? in react-router v4 you should be able to retrieve the same info from either `match` or `location` – Anthony Kong May 30 '17 at 07:00
  • @AnthonyKong I'm trying to extract the "test" property.``. I was under the impression that the rendered `` component would have access to an object that held this value. I looked into the `match` and `location` objects and didn't find my prop. – Mark Romano May 30 '17 at 07:04
  • 1
    how about `match.params.test`? – Anthony Kong May 30 '17 at 07:05
  • @AnthonyKong Doesn't seem to be there. Only has `__proto__` – Mark Romano May 30 '17 at 07:07
  • 2
    Don't know why that value is not present, but alternative of that is, pass that value like this: ` } />` and access that by `this.props.test`. – Mayank Shukla May 30 '17 at 07:11
  • 1
    @MayankShukla Thank you. This delivered. Odd that the value wasn't present using the other technique. – Mark Romano May 30 '17 at 07:18

1 Answers1

37

You can pass props to the component by making use of the render prop to the Route and thus inlining your component definition. According to the DOCS:

This allows for convenient inline rendering and wrapping without the undesired remounting explained above.Instead of having a new React element created for you using the component prop, you can pass in a function to be called when the location matches. The render prop receives all the same route props as the component render prop

So you can pass the prop to component like

 <Route path="/" exact render={(props) => (<Home test="hi" {...props}/>)} />

and then you can access it like

this.props.test 

in your Home component

P.S. Also make sure that you are passing {...props} so that the default router props like location, history, match etc are also getting passed on to the Home component otherwise the only prop that is getting passed down to it is test.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • This worked thank you. Odd that the method I tried in my question above didn't work. – Mark Romano May 30 '17 at 07:19
  • 1
    Yeah I had done that analysis in my local setup before answering this, took me some time in that – Shubham Khatri May 30 '17 at 07:20
  • is this the recommended approach? It looks like a quick fix? – pczern Aug 27 '17 at 20:50
  • 1
    you should add the props parameter to the function you pass in and use it in the component 'Home' with {...props} otherwise you would lose the standard props react router v4 passes in – pczern Aug 27 '17 at 20:59
  • 1
    @speedDeveloper, I don't think its a quick fix, and the router props will be passed if you pass it to the component in `render()`. I missed that part in the answer. However I updated it to include the same – Shubham Khatri Aug 28 '17 at 05:25