diff --git a/lib/phoenix_live_view/channel.ex b/lib/phoenix_live_view/channel.ex index f65e3bd5ae..022e474e74 100644 --- a/lib/phoenix_live_view/channel.ex +++ b/lib/phoenix_live_view/channel.ex @@ -347,6 +347,22 @@ defmodule Phoenix.LiveView.Channel do {mod, fun, args} = socket.private.phoenix_reloader apply(mod, fun, [socket.endpoint | args]) + {components, _, _} = state.components + + state = + Enum.reduce(components, state, fn component, state -> + {_, {mod, cid, assigns, _, _}} = component + assigns = %{id: assigns.id, __changed__: %{id: assigns.id}} + + case Diff.update_component(state.socket, state.components, {{mod, cid}, assigns}) do + {diff, new_components} -> + push_diff(%{state | components: new_components}, diff, nil) + + :noop -> + state + end + end) + new_socket = Enum.reduce(socket.assigns, socket, fn {key, val}, socket -> Utils.force_assign(socket, key, val) diff --git a/test/phoenix_live_view/integrations/live_reload_test.exs b/test/phoenix_live_view/integrations/live_reload_test.exs index 1c34aacafa..67a686c304 100644 --- a/test/phoenix_live_view/integrations/live_reload_test.exs +++ b/test/phoenix_live_view/integrations/live_reload_test.exs @@ -47,6 +47,24 @@ defmodule Phoenix.LiveView.LiveReloadTest do assert render(lv) =~ "
Version 2
" end + test "LiveView renders LiveComponents again when the phoenix_live_reload message is received" do + %{conn: conn, socket: socket} = start(@live_reload_config) + + Application.put_env(:phoenix_live_view, :vsn, 1) + {:ok, lv, _html} = live(conn, "/live-component-reload") + assert render(lv) =~ "
Version 1
" + + send( + socket.channel_pid, + {:file_event, self(), {"lib/test_auth_web/live/user_live.ex", :created}} + ) + + Application.put_env(:phoenix_live_view, :vsn, 2) + + assert_receive {:phoenix_live_reload, :live_view, "lib/test_auth_web/live/user_live.ex"} + assert render(lv) =~ "
Version 2
" + end + def reload(endpoint, caller) do Phoenix.CodeReloader.reload(endpoint) send(caller, :reloaded) diff --git a/test/support/live_views/reload_component_live.ex b/test/support/live_views/reload_component_live.ex new file mode 100644 index 0000000000..e4aac24f0c --- /dev/null +++ b/test/support/live_views/reload_component_live.ex @@ -0,0 +1,35 @@ +defmodule Phoenix.LiveViewTest.LiveComponent do + use Phoenix.LiveComponent + + @impl true + def render(assigns) do + {:ok, version} = Application.fetch_env(:phoenix_live_view, :vsn) + assigns = assign(assigns, version: version) + + ~H""" +
+
Version <%= @version %>
+
+ """ + end +end + +defmodule Phoenix.LiveViewTest.ReloadComponentLive do + use Phoenix.LiveView + + def mount(_params, _session, socket) do + {:ok, socket} + end + + @spec render(any()) :: Phoenix.LiveView.Rendered.t() + def render(assigns) do + ~H""" +
+ +
+ """ + end +end diff --git a/test/support/router.ex b/test/support/router.ex index 3420c8500f..5a9112c831 100644 --- a/test/support/router.ex +++ b/test/support/router.ex @@ -45,6 +45,7 @@ defmodule Phoenix.LiveViewTest.Router do live "/log-disabled", WithLogDisabled live "/errors", ErrorsLive live "/live-reload", ReloadLive + live "/live-component-reload", ReloadComponentLive live "/assign_async", AssignAsyncLive live "/start_async", StartAsyncLive