React. Cannot get URL params with useParams() in nested component
I have a simple demo application where you can view quotes individually (QuoteDetail) and view comments under them. I need the url parameters in both components, but I can only get them in the parent component.
App.tsx:
<Switch>
// ...
<Route path="/quotes" exact>
<AllQuotes />
</Route>
<Route path="/quotes/:quoteId">
<QuoteDetail />
</Route>
// ...
</Switch>
QuoteDetail.tsx:
export interface QuoteDetailParams {
quoteId: string;
}
const QuoteDetail: React.FC<QuoteDetailProps> = (props) => {
const match = useRouteMatch();
const { quoteId } = useParams<QuoteDetailParams>();
// ...
console.log(quoteId); // <-- THIS ONE WORKS
// ...
return (
<React.Fragment>
{quote}
<Route path={match.path} exact>
<div className="centered">
<Link className="btn--flat" to={`${match.url}/comments`}>
Show Comments
</Link>
</div>
</Route>
<Route path={`${match.url}/comments`} exact>
<div className="centered">
<Link className="btn--flat" to={`/quotes/${quoteId}`}>
Hide Comments
</Link>
</div>
<Comments />
</Route>
</React.Fragment>
);
};
As you can see, when I click a button to load comments, the url changes from /quotes/1/
to /quotes/1/comments
which should load the Comments
component as well. However, in Comments.tsx
, I can't access the url parameter.
Comments.tsx:
const Comments = () => {
const params = useParams<QuoteDetailParams>();
const { quoteId } = params;
// ...
console.log(params); <-- THIS ONE RETURNS undefined
// ...
return (
<section className={classes.comments}>
<h2>User Comments</h2>
{comments}
</section>
);
};
I have no idea what I'm doing wrong here. Of course, I can pass the parameter using a component prop as well, but this is not desired in my case. Help is appreciated.
I'm using [email protected]
match
-
match.url
is the portion of the URL, it's useful for building nested<Link>
s. -
match.path
is the path pattern used to patch, it's useful for building nested<Route>
s.
Your QuoteDetail
component is using match.url
for building the nested route when it should use match.path
.
<Route path={`${match.url}/comments`} exact> // <-- incorrect route path
...
</Route>
It should be:
<Route path={`${match.path}/comments`} exact>
...
</Route>