Navigating using patch causes liveview to re-mount when using browser back button

I’m trying to find out if this is just fundamentally how it works due to some limitations I’m unaware of, or if this behavior can somehow be changed. I’m hoping someone might be able to shed some light on this before I spend more time going down a rabbit-hole.

Consider this simple LiveView:

defmodule MyAppWeb.NavigationLive do
  use MyAppWeb, :live_view

  def render(assigns) do
    ~H"""
    <p>Hello! You have navigated <%= @count %> times.</p>

    <div class="flex gap-4">
      <.link patch={~p"/navigation?page=#{@page - 1}"}>&lt;- previous page</.link>
      <.link patch={~p"/navigation?page=#{@page + 1}"}>next page -&gt</.link>
    </div>
    """
  end

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def handle_params(params, _url, socket) do
    {:noreply,
     assign(socket,
       page: (params["page"] || "1") |> String.to_integer(),
       count: (socket.assigns[:count] || -1) + 1
     )}
  end
end
  1. When you click a link that causes a patch, only handle_params gets called, as expected.
  2. Click a link again, only handle_params gets called, as expected
  3. Use the browser back button, only handle_params gets called, as expected
  4. Use the browser back button again, it causes the live view to re-mount and lose its state

This feels “wrong” to me, but again, I might just be missing something. I feel like after any one patch, I should be able to hit back and it only invoke handle_params again without needing to re-mount. Is this possible?

Odd, you’re right! I’ve been sitting here trying to reason about this but it feels like a bug to me. I would open an issue.

Thanks for confirming that it also feels odd to you too, I’ll do a little more digging and depending on what I find I might open an issue or maybe even a PR to change it :sweat_smile:

1 Like