Reputation: 3337
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
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
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
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
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