I am using react-router-dom V6, with several different Class components that are connected with various nested within each component. In App.js, I have defined my browser router and routes as follows:
// import omitted for simplicity
function App() {
return (
<BrowserRouter>
<NAVBAR />
<Routes>
<Route path="/" element={ <SHOW_OPTIONS />} />
<Route path="/view_list/:list_id" element={ <SHOW_LIST />} />
<Route path="/authorize" element={ <AUTHORIZE_ITEM /> } />
</Routes>
</BrowserRouter>
);
}
export default App;
Inside of SHOW_OPTIONS, I have a option that brings you to /view_list/:list_id. Inside SHOW_OPTIONS, I need to take the list_id out of the parameter and then query a database for everything with that list_id, then display the list for the end user to browse.
Where I am running into issues is getting that query parameter out of the URL in my class component, since I cannot use any hooks directly from the class.
Here is what my SHOW_LIST class looks like:
export class SHOW_LIST extends Component {
constructor(props) {
super(props);
// Here I want to be able to assign my query
// param to this.state.list_id
this.state = {
list_id: '',
items: '',
items_selected: ''
}
}
componentDidMount() {
getListData(this.state.list_id) // this is == '' right now should be
.then(res => res.json()) // what was passed
.then(data => {
console.log(data);
this.setState({items: data});
})
.catch(err => {
console.log(err);
});
}
buildList() {
// where the list is actually
// built using this.state.items
return (
<div>I made it through!</div>
)
}
render () {
if(this.state.items != null) {
return (
{this.buildList()}
);
} else {
return (
<div id="loading">
Loading...
</div>
);
}
}
}
My link to the SHOW_LIST component looks like this:
<Link to = {{pathname: '/view_list/' list_id}}></Link>
My initial solution was to do something like what's being done here, but since I need to access the query parameters within my class component, I'm not certain this resolution will work. How to pass params into link using React router v6?
CodePudding user response:
Once you've followed the directions of the linked answer and created a custom withRouter
HOC to inject the route path params you access them via the props
object.
Given withRouter
HOC:
const withRouter = WrappedComponent => props => {
const params = useParams(); // <-- these are the path params
// etc... other react-router-dom v6 hooks
return (
<WrappedComponent
{...props}
params={params}
// etc...
/>
);
};
And route path:
path="/view_list/:list_id"
Decorate the component and access them via this.props.params.list_id
. Don't store list_id
prop in state as this is actually an anti-pattern in React (storing passed props in local state).
export class SHOW_LIST extends Component {
constructor(props) {
super(props);
this.state = {
items: null,
items_selected: ''
}
}
componentDidMount() {
getListData(this.props.params.list_id) // <-- consume from props
.then(res => res.json())
.then(data => {
console.log(data);
this.setState({items: data});
})
.catch(console.error);
}
buildList() {
// where the list is actually
// built using this.state.items
return (
<div>I made it through!</div>
)
}
render () {
if (this.state.items !== null) {
return this.buildList();
} else {
return (
<div id="loading">
Loading...
</div>
);
}
}
}
Export the decorated SHOW_LIST
:
export default withRouter(SHOW_LIST);