Hotwire Discussion

How to restore back-button behavior?

Reading the handbook, it is still unclear to me how we should go about restoring the normal behavior of the browser’s back button when using turbo-frames, meaning the back button returns to the previous version of the page rather than the last hard load.

I know in JS frameworks like React there are entire libraries for this. What’s the solution for Turbo?

Thanks!

turbo-frame navigation was previously not linked to history, however it’s just been added to the latest release candidate v7.1.0-rc.1 if you want to try it out.

You can find the unreleased documentation for it at the end of this page:

Thanks! I had already found that stuff though and I am waiting for it to be included in the turbo-rails gem to seriously try it out. I did try it a bit though and I struggled to get it to work. Might have been my setup or something since I was trying to install the turbo js package and bypass the gem.

I am still very confused about how turbo is handling back button presses even after reading all the available documentation, though. Any additional resources you have would be appreciated, but I understand that things are very busy for you.

Thanks for your reply!

If you can specify specifics on what you are confused about, I might be able to help.

Sure let me share some code:

I have a form like this:

  <%= form_tag("/players_manual/select", data: { controller: "form-submitter" }) do %>
    <%= label_tag "Version: " %>
    <%= select_tag "version_id",
      options_for_select(version_option_values, current_version&.id), 
      data: {
        action: "change->form-submitter#submit"
      } %>
  <% end %>

The form-submitter stimulus controller submits the form as soon as a selection is made.

This is the controller action that handles that submit:

  def select
    respond_to do |format|
      format.turbo_stream { render turbo_stream: turbo_stream.replace(:version, partial: "versions/version") }
    end
  end

This replaces the version turbo-frame as expected, but the back button does not take me to the previous version of the page (with the old version of the version turbo-frame) and the url is not changed either. If I understand correctly, I have to change the url manually, and I was doing that at some point, but it didn’t make the back button work.

I may be misunderstanding what is/isn’t supported in turbo, but so far what the docs say isn’t matching up with my experience about how it should be working in my app.

Any help is greatly appreciated!

The 2 areas that might help from the Turbo Handbook are:

When navigating by history (via Restoration Visits), Turbo Drive will restore the page from cache without loading a fresh copy from the network, if possible.

and

Turbo Drive handles form submissions in a manner similar to link clicks. The key difference is that form submissions can issue stateful requests using the HTTP POST method, while link clicks only ever issue stateless HTTP GET requests.

As I understand it, turbo assumes stateful request (POST, PUT/PATCH, DELETE) will change information on the backend and therefore clears the turbo cache so as not to cache pages which may now have updates. On stateless GET requests (link or form GET), Turbo does not clear the cache.

It appears from your code that you are not changing any state on the backend, just navigating different “versions” of a page. Assuming you are not changing any “state”, try changing your form to stateless GET and see if that fixes the Turbo “back” behavior.

<%= form_tag("/players_manual/select", 
     method: :get, data: { controller: "form-submitter" }) do %>