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!