Access React Router history stack
Asked Answered
T

1

8

I have an application where you arrive at a photo album listing via various means (searching, drill down by category, etc). From the album, you click open individual photos and iterate through them using left/right arrows, as well as various editing tools. Each of the iterate/tool actions does a history.push() to add the route to the router history. I am trying to implement a button that will go back to the exact place in the history before you started viewing individual photos. To do that, I'd like to walk the history stack backwards to the point where the the history matches 1 of several patterns then do a history.go(-14) (or whatever) to jump back to the route that started the whole chain.

I've been searching the React router code as well as the HTML5 History object and I don't see any way of accessing the history stack directly so I can walk it back. I'd rather not depend on making each individual photo action push their path to a separate place since that makes it fragile (each photo action is built by a different developer and adding new actions in the future will require previous knowledge to remember to do that).

I can't go to a hard coded path because that would be pushed to the top of the history stack and hitting back arrow would just return you to the last individual photo page instead of the search page that generated the album list in the first place.

Any suggestions on accessing the history stack?

Trainee answered 29/5, 2018 at 1:36 Comment(1)
A bit late but seems like you could just use replace for the internal navigations instead of push, this way it won't generate a new entry in the history and "goBack" will render the last "pushed" route.Cobham
S
8

I do not know if this would be relevant to your case anymore since this is an old question, but I will put this answer here since I had to solve a similar problem myself.

In my own research, I was not able to find a "history.stack" object, but there is a workaround that is also listed here. Basically, you set up a goBack counter that gets passed to the next route as location state. You can then go back the in the stack however many times the counter says to.

let goBack
if (history.location.state) {
    goBack = history.location.state.goBack
} else {
    goBack = -1
}

You can pass location state in React Links by replacing the to= prop with an object.

<Link to={
    { pathname: "/next/path", state: { goBack: goBack - 1 } }
}> Click Here! </Link>

You then just call history.go(history.location.state.goBack) whenever you need to go to the entry route.

If you have the possibility of entering one of the changed routes without hitting the entry one (like a user copies and pastes a URL pointing to a single image), then you can add default behaviour.

if (history.location.state) {
    history.go(history.location.state.goBack)
} else {
    // You can add a default action if a user lands on route from an external link
    history.push('/base/url')
}

This solution could also work if you need more complex behaviours like having 'checkpoint' routes that skip any routes in between as you go back. Just change goBack to be a list of numbers (representing the gaps in between each go-back jump) that you can pop each time you revert back to a checkpoint.

Another solution that might tickle your fancy is to just replace the route instead of pushing it to the stack, but this requires writing a custom component that wraps Link. You can find how to do that here

Soler answered 7/8, 2019 at 23:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.