Traversal direction from current state (outside events)
GriffinSauce opened this issue · 2 comments
Hi, so first off: this API rocks.
I'm looking into implementing transition animations for my app, which is powered by React Router.
For a "slide over" animation I'd need to know the direction of traversal. Now this is pretty easy to determine in the event handlers by comparing indexes but because my routing is handled by another library it would be very helpful to be able to access this information statically as well. (to avoid race conditions between the event handling)
So we have:
currentEntry
provides information about the current stateentries()
provides information about the entire stack- ... what's missing is the user behaviour, how they have traversed the stack, I could have 3 entries but actually a path of 10 back-and-forth actions. That is my actual navigation history.
I'm not sure if this steps too far outside of the scope of the API but I'd love to hear your opinions on this.
In terms of a solution, getting something like lastEntry
would solve the problem, but perhaps a list of last visited entries (probably limited to reasonable number) could support more use cases.
I think you can implement this pretty simply with a currententrychange
listener.
const steps = [];
navigation.addEventListener('currententrychange', (e) => {
if (e.navigationType === 'traversal') {
steps.add({from: e.from, to: navigation.currentEntry});
}
});
That would give you a list of {to, from} objects that represent every history change your application has observed.
Thanks @tbondwilkinson !
I was doing something similar, with the event handler you don't really need the steps, just the last one:
let lastNavigationEvent
window.navigation.addEventListener('currententrychange', event => {
lastNavigationEvent = event
})
export const getLastNavigationDirection = (): 'unknown' | 'back' | 'forward' => {
if (
!lastNavigationEvent || // First landing
lastNavigationEvent.navigationType === 'reload' ||
lastNavigationEvent.navigationType === 'replace'
) {
return 'unknown'
}
const lastIndex = lastNavigationEvent.from.index
const currentIndex = navigation.currentEntry.index
if (currentIndex === lastIndex) return 'unknown'
if (currentIndex > lastIndex) return 'forward'
if (currentIndex < lastIndex) return 'back'
}
(might have some rough edges, just exploring the ideas)
But the main thing I'm worried about is a race-condition between that event handler and the react-router
event handler that triggers re-rendering and animations and I have no control over the latter (aside from maybe monkey-patching it).
So, the green path:
- user triggers navigation
- step is recorded
getLastNavigationDirection
returns correct direction
And the bug:
- user triggers navigation
- app handler triggers,
getLastNavigationDirection
returns incorrect direction - step is recorded .. too late
I guess this can be mitigated by making sure the order of attaching listeners is correct but that feels quite fragile to me. Should I be less worried about that?