Why is there no good solution for back button navigation?

I have been searching for quite some time for a way to make the back button restore the previous state of the DOM, as would be the expected behavior, but still come up empty.

Hotwire will never be a viable replacement for other SPA frameworks until that issue is solved, in my opinion, as other methods have things like ReactRouter, etc that can do this. The docs/manual make it sound like it reloads from cache on restoration visits but that has never worked for me when it comes to partial DOM turbo frame replacement.

I have tried a bunch of different solutions but none of them work as intended. This needs a solution and it needs to be documented very badly. I am trying to contribute by putting my own guides/tutorials/etc out there but this one has me stumped.

So maybe I am just blind and someone has this solved - I would be happy to be corrected. Is there a way to programmatically make a turbo_frame request from within a given frame? If there is, that might help, but only if we can get access to the previous src for that frame. This would allow us to use a single outer frame to control navigation.

Anyway, sorry for ranting a bit. I love Hotwire and I really want it to succeed, but this seems like a big drawback that we should try to solve.

I’ll try to reformulate to see if I understand:

  1. On back operations, the HTML that’s restored doesn’t match the final HTML state of the snapshot before navigating away to the new page. By chance, do you have view-models loaded inside parts of your page (e.g. Vue or React components loaded in spots)?

  2. You’d like to find a way to make a turbo_frame request from within another frame. Are you looking for a programmatic way to do this like saying “look for turbo_frame with id=something and make it change its src to the following url”?

Not using React or Vue. Just ERB templates.

What I want, is only use turbo_frame navigation throughout my app, using a single main turbo_frame to swap out “pages” of my app as the user navigates. Then, when the user clicks the back button, I want to restore the previous version of that turbo frame by reloading it from the previous source.

I have implements some things that are doing 90% of what I want, and I actually made a really nice pattern where you can hit a link inside the page to do a turbo frame navigation with a url such as “http://foo.com/posts/4” and it will simply swap out the frame with no page reloads, but you can also hit that same url from outside the website as a non-turbo_frame request and it will dynamically load the same partial that was used for the turbo_frame navigation inside the full application layout.

And for back button navigation, I have a Stimulus controller that detects the popstate event and changes the main turbo_frame’s src to the current window.location.href to get the main frame to reload its content. That request also dynamically chooses a layout and uses the same partial but wraps it in the correct turbo_frame.

The problem I am having, however, is that I am trying to do pushState on turbo_frame navigations so that I can hit the back button and trigger the Stimulus controller to reload the main turbo_frame, but I can’t seem to get it to only pushState when it’s a forward turbo_frame navigation, and not for other things.

I have tried the mutation observer example that has been kicking around but that seems to fire twice for each src change and I haven’t been able to solve for that without other unwanted side effects.

Hrmm, I’m curious, what’s pushing your desire to do this:

Is it because you don’t have control over the chrome around the turbo_frame? Is it because you’re building a sub-component of a bigger project?

I am just trying to build an SPA. It’s really annoying to have the habit of clicking the back button and accidentally leave the app entirely when you meant to just return to the previous screen.

Pretty sure other SPA frameworks handle this intuitively.

Huh I guess I just never fully understood the stuff here: turbo-site/03_frames.md at main · hotwired/turbo-site · GitHub

Which was linked to me the last time I asked about this here: How to restore back-button behavior? - #2 by tleish

Looks like if you put the right attributes on your links, etc, it all just works nicely.

1 Like