Immutability and Phoenix LiveView
In my daily work I’m going back and forth between Rails and Phoenix with the healthy dose of LiveView. This change in paradigm sometimes shoots me in the leg. This post is written in the form of a self-reminder.
Let me outline the pattern that DOES NOT work:
defmodule AppWeb.PageLive do
use Phoenix.LiveView
def render(assigns) do
~L||
end
def mount(session, socket) do
socket =
socket
|> assign(:work_shift, %WorkShift{})
{:ok, socket}
end
def handle_event("event", params, socket) do
work_shift = socket.assigns.work_shift
# Service performs some work and updates the work_shift
Service.perform(params, work_shift)
{:noreply, socket}
end
end
In the traditional request-response cycle this would work great. But in
the LiveView paradigm, where we don’t leave the view between events and thus
not reloading work_shift
data structure, it fails miserably. It
happens because in the handle_event
method we take the same
version of work_shift
every time and silently discarding the updated
version.
For this to work properly we need to assign the updated work_shift
back into the socket so that the next time we picked where we left. As I
didn’t provide the code of the hypothetical service here, I won’t update
it. Here how the new handle_event
version should look:
def handle_event("event", params, socket) do
work_shift = socket.assigns.work_shift
# Service performs some work and updates the work_shift
{:ok, upd_work_shift} = Service.perform(params, work_shift)
# Assign the updated work shift back into the socket
socket =
socket
|> assign(:work_shift, upd_work_shift)
{:noreply, socket}
end
Happy coding!