Passing both match param and props into react component when using routing

I have a functional react component and want to render some properties for a selected person in my component.

So I first map a simple list with links to each person

      {props.persons.map((person, i) =>{
      return(
     <li key={i}>
      <Link to={`/topics/${person.id}`}>{person.name}</Link>
     </li>
      )
    })}
  </ul>

then I make the route

<Route path={`/topics/:id`} render={() => <Topic persons={props.persons} />} />

as of now I just pass in the persons.

However I also want to be able to pass in the id, so I can find the specific person, and render information about that person. I have tried using the matching property, but that seems to prohibit me from passing in props as well.

Any tips to make a workaround?

Maybe it would be possible to just pass in the properties of the selected person?

EDIT:

Here is what i have tried so far.

   const Topic = (props) =>{
  console.log('props are ', props) //logs array of persons
  return(
    <div>
      <h2>Topic</h2>
      <p>I have been rendered</p>
    </div>
  )
}




 const Topic = ({match}) =>{
  console.log('match is ', match) //logs match parameter, but now i can't access persons
  return(
    <div>
      <h2>Topic</h2>
      <p>I have been rendered</p>
    </div>
  )
}

Upvotes: 2

Views: 1886

Answers (4)

Xelphin
Xelphin

Reputation: 349

You can use useRouteMatch

So in your example:

<Route path={`/topics/:id`} render={() => <Topic persons={props.persons} />} />

Becomes:

<Route exact path={`/topics/:id`} component={() => <Topic persons={props.persons} />}/>

And Topic.js becomes:

import { useRouteMatch } from "react-router-dom"; // Import this
const Topic = (props) =>{
 
  let match =useRouteMatch('/topics/:id').url.split('/'); // Get url and separate with /
  match=match[match.length-1]; // The id is at the end of link, so access last array index
  console.log('match id is ', match);
  console.log('persons is ', persons);

 return(
   <div>
     <h2>Topic</h2>
     <p>I have been rendered</p>
   </div>
 )
}

Upvotes: 1

Garrett Motzner
Garrett Motzner

Reputation: 3230

According to https://reacttraining.com/react-router/web/api/Route:

All three render methods will be passed the same three route props

  • match
  • location
  • history

So in the render prop for the route, you should be able to reference the match and pass it along:

<Route 
  path={`/topics/:id`} 
  render={({match}) => (
    <Topic 
      persons={props.persons} 
      id={match.params.id} 
    />
  )} 
/>

This is because the render function is basically a functional component, and the first parameter to a functional component is the props. (However, you don't have to reference the first parameter as props, you could use renderProps, for example, or restructure it into what you need (match) like I did above)

And then in topic:

 const Topic = ({id, persons}) =>{
  console.log('id is ', id) //logs id parameter
  console.log('persons is ', persons) //logs persons parameter
  return(
    <div>
      <h2>Topic</h2>
      <p>I have been rendered for id {id}</p>
      <code>{JSON.stringify(persons)}</code>
    </div>
  )
}

Upvotes: 1

jered
jered

Reputation: 11581

When you're using the render prop on a <Route> component, the render function is passed an object with the match, location, and history information.

https://reacttraining.com/react-router/web/api/Route/route-props

<Route 
  path={`/topics/:id`} 
  render={({match}) => (
    <Topic id={match.params.id} persons={props.persons} />
  )} 
/>

Upvotes: 2

Hemadri Dasari
Hemadri Dasari

Reputation: 33994

You no need to pass id as a prop to Topic component of route so instead to get the id of path param you can do following in the component to get the id

In the Topic component

You can get the id using

  props.match.params.id

Upvotes: 1

Related Questions