Phx hook in a component not mounted in if case if not wrapped in div

In the following component template, assuming the at the first render data = nil

<%= if @data do %>
  <div id="hook-1234" phx-hook="chart" data="<%= @data %>"></div>
<% else %>
  <%= @spinner %>
<% end %>

the hook is not mounted when data is updated to a truthy value.

However, if the if block is wrapped in a div, it works as expected. Would be nice to know why it works this way.

I think this is the reason:

Limitations

Components must only contain HTML tags at their root. At least one HTML tag must be present. It is not possible to have components that render only text or text mixed with tags at the root.

Phoenix.LiveComponent — Phoenix LiveView v0.20.2

You need your whole component to be wrapped in one div.

I remember having issues as well when I had 2 div’s that weren’t wrapped in a parent div.

~L"""
<div>...</div>
<div>...</div>
"""

Most likely it has to do with how change tracking works.

if and for blocks should work as well, I think.

At least there are examples using them in the docs: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html#module-limitations

<%= for card <- @cards do %>
  <%= live_component @socket, CardComponent, card: card, id: card.id, board_id: @id %>
<% end %>

Besides, I’m not getting any errors like cannot convert component SomeComponent to HTML. which is strange.