Maintaining sessions with LiveView

I have a simple one page app with a selectable list and an image. Based on what is clicked on the list, the image will be changed.

The selectable list is implemented as a LiveComponent and, when an entry is selected, the SelectableList sends a broadcast as:

MyAppWeb.Endpoint.broadcast!(
      "selectable_list_channel",
      "entry_selected",
      %{
        id: socket.assigns.id,
        data: some_selected_data)})

I understand this may not be optimal way to handle this (I am open to suggestions), however it creates another layer of problems.

That is, when the app is called from two tabs (sessions) simultaneously, the user clicking in one session will trigger changes for the other user.

How to properly track that? I have considered using Phoenix Live Session, but it turned out that I can not call put_session from the component. How can I make the component communicate only with the liveview withing session which created them?

Phoenix.PubSub.broadcast!/4 is intended for distributed updates via pub/sub and the fact that it’s so easy to do is one of Elixir/Phoenix’s unique value propositions. Instead of broadcasting, just stick with sending the LiveView process an event for localized updates.

Luckily, because the component and the view run in the same process, sending a message from the LiveComponent to the parent LiveView is as simple as sending a message to self():

defmodule CardComponent do
  ...
  def handle_event("update_title", %{"title" => title}, socket) do
    send self(), {:updated_card, %{socket.assigns.card | title: title}}
    {:noreply, socket}
  end
end
defmodule BoardView do
  ...
  def handle_info({:updated_card, card}, socket) do
    # update the list of cards in the socket
    {:noreply, updated_socket}
  end
end

source: Managing state | LiveComponent docs

4 Likes

Thank you!