1.7.0-rc.3 "no component found matching phx-target of 1" after several `stream_insert`

Hello,
I’m experimenting with 1.7.0-rc.3, the stream feature, as it has been made default when generating live views.

One thing I’ve noticed is that stream_insert in provided examples is issued inside handle_info, with components triggering a message to the live view, which make me wonder if this is a limitation of some sort. In fact, attempt to stream_insert inside a component wasn’t successful at all.

So, I just followed the same principle (component sends a message, the view handles it).

In my case I’m sending a SQL via Ecto to update several elements to leave just one, within a group, with a checkbox. I’m receiving several items back as updated, so I can notify the view about these individually.

First thing first, I can’t send a bunch at once, so instead, I’m using Enum.reduce:

def handle_info({ModuleName, {:updated, cells}}, socket) do
  socket = Enum.reduce(cells, socket, fn c, acc -> stream_insert(acc, :cells, c) end)
  {:noreply, socket}
end

The glitches begin after the first click, if it goes beyond the checkbox group. The socket at the browser side reports:

no component found matching phx-target of 1 undefined utils.js:7:61
    logError utils.js:7
    withinTargets view.js:217
    exec_push js.js:43
    exec js.js:17
    exec js.js:16
    exec js.js:12
    bindClick live_socket.js:648
    withinOwners live_socket.js:434
    owner live_socket.js:430
    withinOwners live_socket.js:434
    bindClick live_socket.js:647
    debounce live_socket.js:881
    debounce dom.js:188
    debounce live_socket.js:880
    withinOwners live_socket.js:434
    owner live_socket.js:430
    withinOwners live_socket.js:434
    debounce live_socket.js:878
    bindClick live_socket.js:646
    (Async: EventListener.handleEvent)
    bindClick live_socket.js:626
    bindClicks live_socket.js:620
    bindTopLevelEvents live_socket.js:520
    doConnect live_socket.js:209
    connect live_socket.js:219
    <anonymous> app.js:34
    <anonymous> app.js:5464

and refuses to add any changes.

Strangely, the modification is still possible among the items within original group that received the first stream_insert.

So, I’m puzzled and asking for any help possible. Thank you!

1 Like

Another point I forgot to mention:

I tried to also reload the whole stream. Again via a PubSub message, which lead to this error:

[error] GenServer #PID<0.6748.0> terminating
** (ArgumentError) existing hook :cells already attached on :after_render.

    (phoenix_live_view 0.18.15) lib/phoenix_live_view/lifecycle.ex:50: Phoenix.LiveView.Lifecycle.attach_hook/4
    (project_web 0.1.0) lib/project_web/live/cell_live/index.ex:62: ProjectWeb.CellLive.Index.handle_info/2
    (phoenix_live_view 0.18.15) lib/phoenix_live_view/channel.ex:271: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
    (stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
    (stdlib 4.0.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

I’m feeling like folks will have a legitimate reason to reload the stream sometimes. What is the solution for this use case?

We don’t have enough information to say what is going on here. How are you rendering your live components? Can you share your template code and component module code?

2 Likes

Hey Cris,

Wow as you said that I moved into my modified index.html.heex and found out my rookie mistake.

<.live_component module={ProjectWeb.CellLive.List} id={UI.u()} slot={nil} streams={@streams} />

<UI.inspect value={assigns} />
<.modal
  :if={@live_action in [:new, :edit]}
  id="cell-modal"
  show
  on_cancel={JS.navigate(~p"/cells")}
>
  <.live_component
    module={ProjectWeb.CellLive.FormComponent}
    id={@cell.id || :new}
    title={@page_title}
    action={@live_action}
    cell={@cell}
    slots={@slots}
    patch={~p"/cells"}
  />
</.modal>

As soon as I changed my id={UI.u()} to something static, the error was totally gone.

I’m too young to Phoenix or LiveView to understand relationships with globally unique IDs. I guess I tried to generate IDs on-the-fly.

So now the only question remained is - how to restart the stream? I wonder if you are able to give the class a lesson here!

Oh, also, is streams passed to the component essentially become a way to interact with it from within a component callbacks?

Thank you again, Chris.

1 Like

To give a context to the stream restarting requirement - I have a filter box that filters the list by name as you type in.