I have a ReactTable
component which accepts an onRowClick
callback function as a property.
I use this component to list an array of Purchase
objects. On click of any Purchase
(row), I want the user to be redirected from /purchases/
to /purchases/:order_number
. I am currently doing this by setting a redirect
state to the order number, and conditionally rendering a Redirect
compoennt:
const Purchases:React.FC<> = ({}) => {
const Purchases: Array<Purchase> = useSelector((state: RootState) => state.shop.purchases)
const [redirect, setRedirect] = useState<string | null>(null)
return (
<Fragment>
<TableContainer
total={null}
data={Purchases}
hide={[]}
onRowClick={(row, idx) => {
setRedirect("/purchase/" + row["Order Number"])
}}
/>
{redirect !== null ? <Redirect to={redirect} /> : null}
</Fragment>
)
}
The problem is, after I go to /purchase/:order_number
, I cannot go back to the previous page because Redirect
does not push to history, it just sets the current route to the next (the one specified in the to
prop). Is there any way to solve this properly?
The version of React Router Dom I am using is 5.2.0
which does NOT support the Navigate
component mentioned in the answer on the question marked as duplicate.
After implementing the solution provided in this question and trying some of the answers from the "duplicate" marked question, I discovered that these solutions actually do NOT WORK!!!
If the user is redirected from routeA
to routeB
and uses a NavLink
to go to routeC
, after clicking the Back button, instead of going back to routeB
, the user is taken to routeA
. This also happens even if the user goes from routeB
to routeC
and then to routeD
....
The way to solve this is to somehow store the current location, or find a way to pass it to the next one via the location
property.
You can simply use local storage
, but I'd suggest passing the location in the state via the Redirect
component:
const location: string = useLocation<{ pathname: string }>().pathname
<Redirect to={{
pathname: "/purchase/12345",
state: { prevLocation: location }
}} />
Then in the component which is rendered on the route /purhcase/:order_number
, you'd use the useHistory
hook provided by react-router-dom
, accept the location
property and have a useEffect
and an event listener which listens for the popstate
event, and run history.push
with the proper location whenever the popstate
event is triggered:
const PurchasePage: React.FC<{ location: { state: { prevLocation: string } } }> = ({ location }) => {
const history = useHistory()
useEffect(() => {
window.addEventListener('popstate', () => history.push(location.state.prevLocation))
return () => window.removeEventListener('popstate', () => history.push(location.state.prevLocation))
}, [history])
return <SomeJsxComponent />
}
This way, you pass the location via props
to the next component which is rendered after the Redirect
and intercept the back
button in order to push to history the previous location.