LiveView JS hook update() function triggers when another element is updated

Hello,

I am having a problem with the update() function of a hook being called when a different element is updated.
My LiveView process receives events two different messages from other processes and the two event handlers update two different assigns, but the hook is called for both of them. I guess this happens because the whole LiveView is rerendered when the assigns changes.
I would like the hook to only trigger when the element that the hook is tied to changes.

How would I get around this?

Below I have made a minimal code example that resembles my use case:

LiveView

defmodule DoubleUpdateWeb.PageLive do
  use DoubleUpdateWeb, :live_view

  @impl true
  def mount(_params, _session, socket) do
    Process.send_after(self(), {:loop1, 0}, 1000)
    Process.send_after(self(), {:loop2, 0}, 2000)

    {:ok, socket, temporary_assigns: [log1: [], log2: []]}
  end

  @impl true
  def handle_info({:loop1, id}, socket) do
    Process.send_after(self(), {:loop1, id + 1}, 1000)
    socket = assign(socket, log1: [{id, "log1"}])

    {:noreply, socket}
  end

  @impl true
  def handle_info({:loop2, id}, socket) do
    Process.send_after(self(), {:loop2, id + 1}, 1000)
    socket = assign(socket, log2: [{id, "log2"}])

    {:noreply, socket}
  end
end

Template

<div id="log1" phx-update="append" phx-hook="TestHook">
  <%= for {id, msg} <- @log1 do %>
    <p id="log1-<%= id %>"><%= msg %></p>
  <% end %>
</div>

<div id="log2" phx-update="append">
  <%= for {id, msg} <- @log2 do %>
    <p id="log2-<%= id %>"><%= msg %></p>
  <% end %>
</div>

Hook (this.el is printed twice in console, but I would expect it to only be called once, since it is only attached to div with id="log1")

Hooks.TestHook = {
  updated() {
    console.log(this.el);
  },
};

Thanks

EDIT: I am using phoenix 1.5.9 & phoenix_live_view 0.15.1

1 Like