What is the pattern for handling Phoenix socket reconnections on LiveView pages?
It hasn’t been a serious problem for me, since my LiveView pages tend to be “use it right now” and not left open overnight or anything, but I notice that when I do leave my pages open for a while (overnight), reconnections happen and the LiveView pages lose their state.
For example, if I have a button that populates a list that I assign to the socket and render in the LiveView template - if I hit the button, see the list, walk away for a few hours then return… the page has been reset to its initial state.
Am I doing something fundamentally wrong, or is this expected behavior?
Is there an easy fix? I guess I could save a copy of the socket’s assigns for the user whenever the state is changed, but that seems cumbersome.
Trying to keep a process and its state alive, even while the user is disconnected, seems more cumbersome than just saving the state to the database and loading it again when the user comes back. What if the user doesn’t come back to the page for 7 days, or a month, or ever? You wouldn’t want to keep the process alive for that long. (Remember each LiveView gets its own process)
But the user isn’t really disconnected. Suppose the page is showing monitoring data for a server where there’s no constant user input, but there’s a need to have the display settings maintained through spurious browser reconnects?
Typically, javascript client frameworks I’ve worked with handle reconnects seamlessly in the background without dumping state.
But if this is expected LiveView behavior, then okay. I’ll work around it if I need to.
I saw the form recovery docs, and wasn’t sure it applied that well since I don’t even always have an actual form element on my LiveView Pages. I’ll play around with it, though.
Depending on the use case, another possibility is keeping the state in URL params. So if, like your example, you are just toggling a list shown or hidden, you could use live_patch e.g.
<%= live_patch "Show list A",
to: Routes.live_path(@socket, MyAppWeb.PageLive, A: "show") %>
and handle_params to change the state
def handle_params(%{"A" => "show"}, _url, socket) do
# Stuff
{:noreply, socket}
end