I'm trying to load a details view based on a react-router-dom route that should grab the URL parameter (id) and use that to further populate the component.
My route looks like /task/:id and my component loads fine, until I try to grab the :id from the URL like so:
import React from "react";
import { useParams } from "react-router-dom";
class TaskDetail extends React.Component {
componentDidMount() {
let { id } = useParams();
this.fetchData(id);
}
fetchData = id => {
// ...
};
render() {
return <div>Yo</div>;
}
}
export default TaskDetail;
This triggers the following error and I'm unsure where to correctly implement useParams().
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
The docs only show examples based on functional components, not class based.
Version <= 5:
You can use withRouter to accomplish this. Simply wrap your exported classed component inside of withRouter and then you can use this.props.match.params.id to get the parameters instead of using useParams(). You can also get any location, match, or history info by using withRouter. They are all passed in under this.props
Using your example it would look like this:
import React from "react";
import { withRouter } from "react-router";
class TaskDetail extends React.Component {
componentDidMount() {
const id = this.props.match.params.id;
this.fetchData(id);
}
fetchData = id => {
// ...
};
render() {
return <div>Yo</div>;
}
}
export default withRouter(TaskDetail);
Simple as that!
Params get passed down through props on the match object.
props.match.params.yourParams
source: https://redux.js.org/advanced/usage-with-react-router
Here is an example from the docs destructing the props in the arguments.
const App = ({ match: { params } }) => {
return (
<div>
<AddTodo />
<VisibleTodoList filter={params.filter || 'SHOW_ALL'} />
<Footer />
</div>
)
}
Since hooks wont work with class based components you can wrap it in a function and pass the properties along:
class TaskDetail extends React.Component {
componentDidMount() {
const { id } = this.props.params;
// ...
}
}
export default (props) => (
<TaskDetail
{...props}
params={useParams()}
/>
);
But, like @michael-mayo said, I expect this is what withRouter is already performing.