You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Phoenix LiveView的phx-update="stream"块中更新assigns

Phoenix LiveView Stream块内无法获取动态Assigns的问题解决

问题本质是Phoenix LiveView的Stream渲染优化机制:带有phx-update="stream"属性的容器,其内部模板仅在Stream数据(@streams.searched_notes)变更时才会重新渲染,普通Assigns(如@online_users_map)的更新不会触发该区域的模板重新计算,因此你在Stream块内的inspect始终显示初始的空值。

下面是两种可行的解决办法:

方法一:触发Stream条目重渲染

当online_users_map更新时,手动触发Stream条目重新渲染(无需重新加载数据,仅让LiveView重新渲染现有条目)。在处理Phoenix Presence更新的handle_info回调中,更新完online_users_map后调用stream/3:

def handle_info(%Presence.PresenceStateChanged{} = event, socket) do
  online_users_map = # 此处编写生成最新在线用户映射的逻辑
  socket = assign(socket, :online_users_map, online_users_map)
  # reset: false 表示保留现有Stream数据,仅重新渲染条目
  {:noreply, stream(socket, :searched_notes, socket.assigns.searched_notes, reset: false)}
end

执行后LiveView会重新渲染所有Stream条目,此时就能获取到最新的@online_users_map。

方法二:用LiveComponent封装条目

将单个笔记条目封装为LiveComponent,把note和online_users_map作为props传入。LiveComponent会在props更新时自动重渲染,不受Stream容器的渲染限制:

  1. 创建LiveComponent:
# lib/your_app_web/live/note_component.ex
defmodule YourAppWeb.NoteComponent do
  use YourAppWeb, :live_component

  def render(assigns) do
    ~H"""
    <li class="pb-2 sm:pb-2 mt-2 flex flex-row " id={@id}>
      <!-- 根据online_users_map判断作者在线状态 -->
      <%= if Map.has_key?(@online_users_map, @note.author_id) do %>
        <span class="text-green-500 ml-2">在线</span>
      <% end %>
      <!-- 渲染其他笔记内容 -->
      <div><%= @note.content %></div>
    </li>
    """
  end
end
  1. 修改原模板中的条目渲染:
<div>
  <%= inspect(@online_users_map) %>
  <ul
    phx-update="stream"
    phx-viewport-top={@page_no > 1 && "prev-page"}
    phx-viewport-bottom={!@end_of_timeline? && "next-page"}
    phx-page-loading
    id="searched_notess"
    class={[
      if(@end_of_timeline?, do: "pb-4", else: "pb-[calc(200vh)]"),
      if(@page_no == 1, do: "pt-4", else: "pt-[calc(200vh)]")
    ]}
  >
    <%= for {dom_id, note} <- @streams.searched_notes do %>
      <%= live_component @socket, YourAppWeb.NoteComponent, id: dom_id, note: note, online_users_map: @online_users_map %>
    <% end %>
  </ul>
</div>

这样每当@online_users_map更新时,所有NoteComponent都会接收新的props并重新渲染,正确展示作者在线状态。

内容的提问来源于stack exchange,提问作者Jason O.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:00:38