Capability: react to a server-side message arriving at this
LiveView. Used for PubSub broadcasts, self-scheduled timers
(Process.send_after/3), monitor/DOWN messages, and the like.
Structurally parallel to actions do action :foo do ... end end:
a messages do block holds N message pattern do ... end
clauses. Each clause body is a sequence of ops drawn from the
same vocabulary as actions — run, effect, set.
Shape
messages do
message :tick do
set :ticks, rx(@ticks + 1)
end
message {:custom_msg, msg}, [:msg] do
run fn socket ->
assign(socket, :last_msg, msg)
end
end
message :pinged do
run fn socket ->
socket
|> assign(:broadcasts, socket.assigns.broadcasts + 1)
|> push_event("ack", %{})
end
effect fn socket ->
require Logger
Logger.info("pinged: #{socket.assigns.broadcasts}")
end
end
endrun fn socket -> ... end vs action's run fn assigns -> ... end
Messages frequently want the full Phoenix.LiveView API:
push_event, push_patch, redirect, start_async,
assign_async, etc. All operate on socket. So run inside a
message body takes the socket and should return the socket.
Action run fn bodies take assigns because actions are
state-mutation-focused — the assigns-shaped contract works well
there. Messages and actions diverge intentionally on this point.
set :field, rx(...)
Same shape and semantics as inside an action. The reactive
expression evaluates against the current state at fire time.
Useful for the common "this message just bumps state" case
without writing a full run fn.
Bind list
The optional second arg to message names the variables in the
pattern that the body should see. So message {:custom, x}, [:x]
makes x available in the body's run fn body. They're already
bound by the pattern itself; the bind list is currently a docs
hint and reserved for future validator checks.
Layer
Layer 1: the body is a sequence of declarative ops. set ..., rx(...)
participates in layer 2 (reactive graph); run/effect are plain
Elixir. Reactive recompute runs after the body so downstream
calculate :foo, rx(...) updates correctly.
Summary
Functions
A single message pattern do <ops> end clause inside a
messages block. bind is a list of atom names appearing in
the pattern that should be in the body's scope alongside the
socket.
Functions
A single message pattern do <ops> end clause inside a
messages block. bind is a list of atom names appearing in
the pattern that should be in the body's scope alongside the
socket.
The body is a sequence of op calls (run/effect/set). Each
is captured at compile time and stored on the clause; the
runtime executes them in order, passing the socket through.
Top-level messages do ... end block. The body should contain
one or more message/2 or message/3 calls.