history icon indicating copy to clipboard operation
history copied to clipboard

Run async side effects before url change

Open nordsimon opened this issue 6 years ago • 5 comments

This issue might sound like an anti pattern but the idea is only to implement standard browser behaviour.

Generally, in a non SPA app, when user clicks an A tag the browser waits for the response in the background and does not update the url before response arrives (or fails after timeout). In SPA apps the general pattern is to update the url and then rerender, fetch data etc. based on the url. While this is ok most of the time it creates new problems like

  • If your SPA triggers on url change. You will probably render some sort of loading state directly on url change, this is most of the time annoying and unncessary
  • Tracking (and other tools) that listens to url change will trigger before data has arrived. For example google analytics

Generally I'm looking for a solution to run a side effect (like fetching data) before transition is made. This way we can implement something similar to browser behaviour and ensure that needed data is in place when actual url change is made.

Of course you could implement this in your app (like react) but I think that history is a good place for such a logic, mostly because it is already standard behaviour in browsers

I would be happy to contribute to this feature if we find it meaningful

nordsimon avatar Dec 29 '18 10:12 nordsimon

I believe that this would require a major re-implementation of the library. I did a similar thing with hickory and it works nicely, but comes with caveats. The complication is because if the navigation isn't instant, then it needs to be cancellable (the user may click another link while the current one's async actions are running).

pshrmn avatar Dec 29 '18 16:12 pshrmn

Yes it might not work with current api but i was planning to add it as an optional thing in the transitionmanager. It is already callback based so it might support this. But of course there will be complications

Regarding new url during async work that could be managed as well I think

I opened this issue to see if there is any interest in this problem or any other good solutions

Your package looks nice, I was thinking about writing my own with the same api as history to make it a drop in replacement but if more people want this feature in the history package it would be good to land it there instead

nordsimon avatar Dec 29 '18 17:12 nordsimon

This is a great feature to add in v6, I think. It's tricky though because we don't always have control of when the new URL appears in the address bar. In the case of a PUSH or REPLACE we do (we are changing the URL), but not on a POP (the URL has already changed).

mjackson avatar Mar 27 '19 01:03 mjackson

can't we use the transition manager instance for that?

I will also happily contribute for that feature. Will make my life easier :)

goldylucks avatar Jul 10 '19 21:07 goldylucks

In a previous issue, it was pointed out that a pre-configured custom history object could be passed to a Router component, rather than using a BrowserRouter component.

Here's a way you might be able to use this to accomplish what you want, using the current version of React Router.

  1. Wrap the original history object such that you intercept calls to push.
  2. Pass the wrapped history object to Router, and use Router instead of BrowserRouter.
  3. When push is called, store the destination URL in a "transitioningTo" variable somewhere.
  4. Perform any async requests. You probably want to show a spinner or otherwise tell the user to wait while this is happening.
  5. Call the original, wrapped history.push when the async requests are completed.

This doesn't solve history.pop or page refreshes, so you would still need to have a page that looks reasonable if the user navigates to it directly before the async requests are completed.

douglas-treadwell avatar Apr 20 '20 01:04 douglas-treadwell