Please I need help on react-router-dom, I am new to the library and can seem to find any solution since. I am getting three results from an api call, in which I map over the data to render it on UI, now what I need now is that if I click on a row on one of this list, I want it to take me to a screen showing the details of only that single thing I clicked on.
import React, { Component } from "react";
export default class User extends Component {
state = { userDetails: "" };
componentDidMount() {
axios.get(`https://urlforapi.com`)
.then(({ data }) => {
this.setState({
userDetails: data
});
});
}
render() {
const { userDetails } = this.state;
return (
<div>
{userDetails
? userDetails.map(info => {
return (
<Link to="/home/userDetails">
<div key={info.id}>
<p>{info.name}</p>
</div>
<div>
<p>{info.age}</p>
</div>
<div>
<p>{info.description}</p>
</div>
</Link>
);
})
: null}
</div>
);
}
}
Send the state in the route transition.
Using react-router-dom
v5
Declarative Navigation - Link to
You can pass some state unique to the mapped entry, like info.id
along with the route push that happens when the link is clicked. This obfuscates the data from the user as you aren't leaking information out to the ui (i.e. the browser).
<Link
to={{
pathname: '/home/userDetails',
state: { infoId: info.id },
}}
>
Imperative Navigation - useHistory hook
const history = useHistory();
...
history.push({
pathname: '/home/userDetails',
state: { infoId: info.id },
});
You can then unpack the state from the location
prop/object on the component being returned by that route. Use guards in case a user has navigated to '/home/userDetails'
from elsewhere, as state
may be undefined.
If passed route props:
props.location && props.location.state && props.location.state.infoId
or
props.location?.state?.infoId
If using function components then you can also use the useLocation
React hook:
const { state: { infoId } = {} } = useLocation();
Using react-router-dom
v6
Declarative Navigation - Link or Navigate components
The link API changed a bit in v6, the state
is now a prop.
<Link
to='/home/userDetails'
state={{ infoId: info.id }}
>
or using the Navigate
component, the spiritual successor/replacement to the v5 Redirect
component
<Navigate
to="/home/userDetails"
state={{ infoId: info.id }}
/>
Imperative Navigation - useNavigate hook
const navigate = useNavigate();
...
navigate('/home/userDetails', { state: { infoId: info.id } });
You can then unpack the state from the location
object on the component being returned by that route. Use guards in case a user has navigated to '/home/userDetails'
from elsewhere, as state
may be undefined.
const { state: { infoId } = {} } = useLocation();
<Link to={`/home/userDetails/${info.id}`>
or (RRDv5)
const history = useHistory();
...
history.push(`/home/userDetails/${info.id}`);
or (RRDv6)
const navigate = useNavigate();
...
navigate(`/home/userDetails/${info.id}`);
And retrieve the param from the match
prop in the returned route component. For example if the route looks like this:
Using react-router-dom
v5
<Route path="/home/userDetails/:infoId" component={Detail} />
Then in the component get id from the match
route prop:
props.match.params.infoId
And in the case of function components, the useParams
React hook:
const { infoId } = useParams();
Using react-router-dom
v6
<Route path="/home/userDetails/:infoId" element={<Detail />} />
There is only the useParams
hook in v6, there are no route props.
const { infoId } = useParams();
The user can see this, but you don't have to use the guard pattern to access since by definitions it'll be defined by the route (though infoID
can still be defined if the user types in an invalid id).
Using react-router-dom
v5
Declarative Navigation - Link to
<Link
to={{
pathname: '/home/userDetails',
search: `?infoId=${info.id}`,
}}
>
Imperative Navigation - useNavigate hook
const history = useHistory();
...
history.push({
pathname: '/home/userDetails',
search: `?infoId=${info.id}`,
});
You can then unpack the infoId
query param from the location
prop/object on the component being returned by that route.
If passed route props:
props.location && props.location.search
or
props.location?.search
If using function components then you can also use the useLocation
React hook:
const { search } = useLocation();
Then create a URLSearchParams object and access the infoId
parameter.
const searchParams = new URLSearchParams(search);
const infoId = searchParams.get("infoId");
Using react-router-dom
v6
Declarative Navigation - Link or Navigate components
The link API changed a bit in v6, the state
is now a prop.
<Link
to={{
pathname: '/home/userDetails',
search: `?infoId=${info.id}`,
}}
>
or using the Navigate
component, the spiritual successor/replacement to the v5 Redirect
component
<Navigate
to={{
pathname: '/home/userDetails',
search: `?infoId=${info.id}`,
}}
/>
Imperative Navigation - useNavigate hook
const navigate = useNavigate();
...
navigate({
pathname: '/home/userDetails',
search: `?infoId=${info.id}`,
});
You can then unpack the infoId
query param from the useSearchParams
hook.
const [searchParams] = useSearchParams();
const infoId = searchParams.get("infoId");
New in v6.4.0 is the createSearchParams utility function.
<Link
to={{
pathname: '/home/userDetails',
search: createSearchParams({ infoId: info.id}),
}}
>
or
navigate({
pathname: '/home/userDetails',
search: createSearchParams({ infoId: info.id}),
});
In react-router-dom@6
the route props and withRouter
HOC were removed. To access the old "route props" in RRDv6 you'll need to create your own withRouter
HOC replacement that can use the React hooks and inject props that can be used in React class components.
import { useLocation, useParams, /* other hooks */ } from 'react-router-dom';
const withRouter = WrappedComponent => props => {
const location = useLocation();
const params = useParams();
// other hooks
return (
<WrappedComponent
{...props}
{...{ location, params, /* other hooks */ }}
/>
);
};
Decorate the component and access props:
class MyComponent extends React.Component {
...
this.props.location.state;
this.props.params;
...etc...
...
};
export default withRouter(MyComponent);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With