rustwasm / gloo

A modular toolkit for building fast, reliable Web applications and libraries with Rust and WASM
https://gloo-rs.web.app
Apache License 2.0
1.75k stars 144 forks source link

[history] Restoring scroll position when the back button is pressed #322

Open norbertkeri opened 1 year ago

norbertkeri commented 1 year ago

Hey,

I started dabbling with the yew framework, and I got to the point where I would like to implement scroll restoration. I realize this is not the yew issue tracker, but I think it's very related to gloo-history.

The problem in a nutshell:

The reason you are at the top is because when the browser renders the page from the bfcache, and tries resetting the y scroll position, the data for the page is not yet there, there is nothing to scroll down to. The XHR request is still in-flight at this point and it will arrive eventually, but the browser already made an attempt to reset the scroll position.

I could implement scroll restoration in userland:

The missing piece is the check for the back button. I went into the yew source code to see if there is any indication whether the back button was pressed, but there isn't any. I tried grepping for popstate, since it must definitely be listening on that, otherwise the back button would not work at all with yew apps, but found nothing. Digging further, I found out the reason I'm not finding anything in the yew_router crate, is because all history handling is actually handled by gloo_history!

I found the relevant line at:

https://github.com/rustwasm/gloo/blob/master/crates/history/src/browser.rs#L283

If the notify_callbacks could pass an extra parameter that signals that it was a popstate event, I could implement scroll restoration. React router supports this by exposing a "history action": https://reactrouter.com/en/main/start/concepts#definitions

Can anyone give me some tips on how to implement this, and confirm this is actually a good way to do this? I don't have that much rust knowledge, but I could maybe give it a try.

futursolo commented 1 year ago

If the notify_callbacks could pass an extra parameter that signals that it was a popstate event

I think you can try to store a state with the history entry? If it doesn't have an entry with the previous scroll position, then it should be a new entry.