Prepend/append in real-time update via Phoenix.PubSub

Hello,
First of all - Phoenix.PubSub is awesome! Learning from a pragmaticstudio video, I managed to implement real-time update of my app.

#context
  def subscribe do
    Phoenix.PubSub.subscribe(App.PubSub, "messages")
  end

  def create_message(attrs \\ %{}) do
    %Message{}
    |> Message.changeset(attrs)
    |> Repo.insert()
    |> broadcast(:message_created)

  end
  
  def broadcast({:ok, message}, event) do

    Phoenix.PubSub.broadcast(
      App.PubSub,
      "messages",
      {event, message}
    )
    {:ok, message}
  end

#live view

def mount(params, session, socket) do
    if connected?(socket), do: Messages.subscribe()
   (...)
end

  def handle_info({:message_created, message}, socket) do
    socket =
      update(
        socket,
        :messages,
        fn messages -> [message | messages] end
      )

    {:noreply, socket}
  end

Thus when I record data via App.Context.create_message I can see real time updates from this list

<%= for message <- @messages do %>
  <%= message.body %>
<% end %>

However, the new “message” comes before the others, i.e. append.
refreshed page:

message 1 - Hello
message 2 - Hiii

, but after sending a new request and broadcasting the new info I get

message 3 - 'sup?
message 1 - Hello
message 2 - Hiii

My question here is how to prepend that new message, to be after message 2? Since I don’t use phx-update (DOM patching & temporary assigns — Phoenix LiveView v0.17.9) I tried this

 <div id="messages" phx-update="prepend">
    <%= for message <- @messages do %>
      <%= message.body %>
    <% end %>
 </div>

But it didn’t work

I don’t know your use case but for me it makes sense to add new messages to the top (prepend), therefore I would change the code to:

|> Repo.insert()
|> Enum.reverse()
|> broadcast(:message_created)

You have the current order of messages because you are prepending them to the list of messages in this code:

Doing the opposite (append) would be expensive, but you can also reverse the list of messages:

fn messages -> [message | messages] |> Enum.reverse() end