nallwhy
How to replace LiveView stream with new items? (reset or re-assigning)
I expected that the existing stream to be replaced with new items when stream is assigned again, but it isn’t.
It crashes with ** (ArgumentError) existing hook :messages(stream name) already attached on :after_render.
@impl true
def update(assigns, socket) do
...
socket =
socket
|> assign(assigns)
|> assign_messages(new_channel_name)
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<div>
<.h2># <%= @channel_name %></.h2>
<p>Your ID: <%= @session_id %></p>
<div id="messages" class="h-96 overflow-y-auto" phx-update="stream" phx-hook="ChatMessages">
<div :for={{message_id, message} <- @streams.messages} id={message_id} class="mt-4">
<p>User id: <%= message.user_id %></p>
<p><%= message.created_at %></p>
<p><%= message.body %></p>
</div>
</div>
...
</div>
"""
end
defp assign_messages(socket, channel_name) do
{:ok, messages} = Chat.list_messages(channel_name)
socket
|> stream(:messages, messages)
...
end
You can test it on the page below, by changing channel.
Is it possible to replace stream with new items? (re-assigning)
page: Chat in Elixir · Json Media
code: json_corp/apps/json_corp_web/lib/json_corp_web/live/playgrounds/chat_live/channel.ex at chat · nallwhy/json_corp · GitHub
Marked As Solved
rio517
FYI, this is now implemented.
Resetting a stream
To empty a stream container on the client, you can pass
:resetwith an empty list:stream(socket, :songs, [], reset: true)Or you can replace the entire stream on the client with a new collection:
stream(socket, :songs, new_songs, reset: true)
Also Liked
codeanpeace
At the moment, you can stream_insert to update or add or stream_delete to delete individual elements e.g. message within @streams.messages within an existing stream. Emptying/clearing out an existing stream at the @streams.messages level isn’t currently supported, but it is on the roadmap.
rio517
FYI, if you do replace a stream, note that the entire collection in the stream is sent down the wire. For many items, that can be quite large. I generated a new app with the default CRUD UI and generated liveview scafolding for posts with a title, ID. For 1000 items, the WebSocket frame had 1.3MB of data sent down the wire. Consider using infinite scrolling as discussed in the guide here: Bindings — Phoenix LiveView v1.2.5








