Closed borisgoro closed 1 month ago
Code: https://github.com/borisgoro/hooks_test
I created the app with mix phx.new hooks_test and tried upgrading the live view version to 0.20.12, ..., 1.0.0-rc.6 with the same result.
mix phx.new hooks_test
Define two hooks:
const liveSocket = new LiveSocket('/live', Socket, { params: { _csrf_token: csrfToken }, hooks: { Hook1: { mounted () { console.log('Hook1 mounted') } }, Hook2: { mounted () { console.log('Hook2 mounted') } } } })
and a LiveComponent with a "panel" for each hook:
defmodule HooksTestWeb.TestLiveComponent do use HooksTestWeb, :live_component @impl true def render(%{panel: 1} = assigns) do ~H""" <div id="panel1" phx-hook="Hook1" class="mt-2 p-2 border-2"> <.panel panel="1" target={@myself} /> </div> """ end def render(%{panel: 2} = assigns) do ~H""" <div id="panel2" phx-hook="Hook2" class="mt-2 p-2 border-2"> <.panel panel="2" target={@myself} /> </div> """ end def panel(assigns) do ~H""" <div><%= "Panel #{@panel}" %></div> <button class="mt-2 p-1 border-2" phx-click="panel1" phx-target={@target}>Panel 1</button> <button class="mt-2 p-1 border-2" phx-click="panel2" phx-target={@target}>Panel 2</button> """ end @impl true def handle_event("panel1", _, socket) do {:noreply, assign(socket, panel: 1)} end def handle_event("panel2", _, socket) do {:noreply, assign(socket, panel: 2)} end end
Hook1.mounted() is called on the initial render, but Hook2.mounted() is not called when the Panel 2 button is clicked.
Identical code (without the phx-target stuff) works fine in a LiveView:
defmodule HooksTestWeb.HomeLive do use Phoenix.LiveView, layout: {HooksTestWeb.Layouts, :app} @impl true def mount(_params, _session, socket) do {:ok, assign(socket, panel: 1)} end # @impl true # def render(assigns) do # ~H""" # <.live_component id="test-lc" panel={@panel} module={HooksTestWeb.TestLiveComponent} /> # """ # end @impl true def render(%{panel: 1} = assigns) do ~H""" <div id="panel1" phx-hook="Hook1" class="mt-2 p-2 border-2"> <.panel panel="1" /> </div> """ end def render(%{panel: 2} = assigns) do ~H""" <div id="panel2" phx-hook="Hook2" class="mt-2 p-2 border-2"> <.panel panel="2" /> </div> """ end def panel(assigns) do ~H""" <div><%= "Panel #{@panel}" %></div> <button class="mt-2 p-1 border-2" phx-click="panel1">Panel 1</button> <button class="mt-2 p-1 border-2" phx-click="panel2">Panel 2</button> """ end @impl true def handle_event("panel1", _, socket) do {:noreply, assign(socket, panel: 1)} end def handle_event("panel2", _, socket) do {:noreply, assign(socket, panel: 2)} end end
Browser console displays Hook1 mounted on initial render, nothing when buttons are clicked.
Hook1 mounted
Browser console displays Hook1 mounted and Hook2 mounted when the corresponding button is clicked.
Hook2 mounted
We should try address this but, given that the root element of live components are treated especially, we should forbid phx-hook at the root of LiveComponents.
Environment
Code: https://github.com/borisgoro/hooks_test
I created the app with
mix phx.new hooks_test
and tried upgrading the live view version to 0.20.12, ..., 1.0.0-rc.6 with the same result.Define two hooks:
and a LiveComponent with a "panel" for each hook:
Hook1.mounted() is called on the initial render, but Hook2.mounted() is not called when the Panel 2 button is clicked.
Identical code (without the phx-target stuff) works fine in a LiveView:
Actual behavior
Browser console displays
Hook1 mounted
on initial render, nothing when buttons are clicked.Expected behavior
Browser console displays
Hook1 mounted
andHook2 mounted
when the corresponding button is clicked.