-
-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Description
What is the new or updated feature that you are suggesting?
Allowing the children
of the Route
component to be a function/render prop and pass in the match
object
const BlogPost = ({ id }: { id: string }) => {
return <div>BlogPost {id}</div>
}
export const Routes = () => {
<Route path={'/blog-posts/:blogPostId' as const}>
{(match) => <BlogPost id={match.params.blogPostId} />}
</Route>
}
Why should this feature be included?
In previous versions of react-router
we were able to use a render
prop on the Route
component to render our pages/components when matching the given path and this render prop was given a routeProps
argument. I agree that most of the props in this routeProps
were not very useful as we could just use the hooks/HOC to get them, but the match
object was very useful and informative as it allowed us to keep the path/params logic in the routes. The TypeScript inferance that we had on top of that was amazing, it allowed us to have strongly typed params in the path and pass them down as props to the rendered components rather than rely on the "unreliable" useParams
.
This implementation here uses react-router@5. Passing the path
prop as a const
allowed us to be 100% sure we had the blogPostId
param and that we were passing this down declaratively to our BlogPost
:
const BlogPost = ({ id }: { id: string }) => {
return <div>BlogPost {id}</div>
}
export const Routes = () => {
<Route
path={'/blog-posts/:blogPostId' as const}
render={({ match }) => (
<BlogPost id={match.params.blogPostId} />
)}
/>
}
With the react-router@6 way we have to trust that the BlogPost
component is actually rendered under a Route
that has the blogPostId
param in its path. We are passing a generic to the useParam
hook and essentially saying: give me whatever param you have from the URL but just cast it to what I think is there, might not be though.
const BlogPost = () => {
const { blogPostId } = useParams<{ blogPostId: string }>()
return <div>BlogPost {blogPostId}</div>
}
export const Routes = () => {
<Route path={'/blog-posts/:blogPostId' as const}>
<BlogPost />
</Route>
}
Funny enough I had made mistake in the react-router@6 example at the start as I had written it like this, which TypeScript is fine with but id
does not actually exist in the params, it should be blogPostId
:
const BlogPost = () => {
const { id } = useParams<{ id: string }>()
return <div>BlogPost {id}</div>
}
export const Routes = () => {
<Route path={'/blog-posts/:blogPostId' as const}>
<BlogPost />
</Route>
}
Thank you for considering this!