Props & data
Async Assigns
assign_async's AsyncResult reaches React as loading, ok and failed
- assign_async
- AsyncResult encoder
Key concepts
assign_async/3
in mount/3
starts work in a linked process and immediately returns a
Phoenix.LiveView.AsyncResult
in its loading state. When the work finishes, LiveView updates the assign for
you — either to a successful result or to a failure — with no handle_info/2
to write.
defmodule MyAppWeb.AsyncLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, socket |> assign(:mode, :ok) |> load_stats()}
end
def render(assigns) do
~H"""
<div class="space-y-4">
<div class="flex gap-2">
<button type="button" class="rounded-md border px-3 py-1" phx-click="reload">
Reload
</button>
<button type="button" class="rounded-md border px-3 py-1" phx-click="fail">
Simulate failure
</button>
</div>
<%!-- diff={false}: the AsyncResult swaps state wholesale (loading -> ok
or failed), so there is nothing worth patching — send the whole
value every time instead of a diff. --%>
<.react name="Async" stats={@stats} diff={false} socket={@socket} />
</div>
"""
end
def handle_event("reload", _params, socket) do
{:noreply, socket |> assign(:mode, :ok) |> load_stats()}
end
def handle_event("fail", _params, socket) do
{:noreply, socket |> assign(:mode, :error) |> load_stats()}
end
defp load_stats(socket) do
mode = socket.assigns.mode
assign_async(socket, :stats, fn ->
Process.sleep(400)
case mode do
:ok -> {:ok, %{stats: %{stars: 1234, downloads: 98_765}}}
:error -> {:error, "the upstream service is unavailable"}
end
end)
end
endHow it works
The AsyncResult
struct is passed straight to React as a prop, unchanged, because LiveReact
ships an encoder for it. React reads loading, ok
and failed
directly off the prop rather than the server flattening them into three
separate assigns and deciding which one to send.
"Reload" re-runs the same async work; "Simulate failure" reruns it in a
mode that returns {:error, reason}
instead, so all three states — loading, ok and failed — are reachable from
the page itself.