Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

phx-hook not working on an element mounted by a LiveComponent #3423

Open
borisgoro opened this issue Sep 13, 2024 · 1 comment
Open

phx-hook not working on an element mounted by a LiveComponent #3423

borisgoro opened this issue Sep 13, 2024 · 1 comment
Labels

Comments

@borisgoro
Copy link

borisgoro commented Sep 13, 2024

Environment

  • Elixir version (elixir -v): 1.17.2
  • Phoenix version (mix deps): 1.17.14
  • Phoenix LiveView version (mix deps): 0.18.3, 0.20.17, 1.0.0-rc.6
  • Operating system: macOS Sonoma
  • Browsers you attempted to reproduce this bug on (the more the merrier): Safari, Chrome
  • Does the problem persist after removing "assets/node_modules" and trying again? Yes/no: yes

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:

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

Actual behavior

Browser console displays Hook1 mounted on initial render, nothing when buttons are clicked.

Expected behavior

Browser console displays Hook1 mounted and Hook2 mounted when the corresponding button is clicked.

@SteffenDE SteffenDE added the bug label Sep 15, 2024
@josevalim
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants