I think this is where the mismatch comes from. Indeed in the case of {:noreply, state} or {:ok, state} it feels like you’re only transforming state. But there are in many places other options as well.
mount/3can also return{:ok, state, keyword}handle_call/3can also return{:reply, term, state}handle_event/3can also return{:reply, map, state}
Those callbacks are not just transformations of state, but transformations of state is just one of potentially many things they do and return information about. Sometimes those other things are even the only thing happening with no changes to state.
E.g. for me most simple callbacks look like this:
def handle_event("something", _, socket) do
socket =
socket
|> assign(a: :something)
|> update(:b, fn x -> x + 1 end)
{:noreply, socket}
end
The state transformation is neatly contained in a pipeline, but the return of that state transformation is separate to the transformation itself. It doesn’t belong in the pipeline. This becomes apparent if the code changes and you need to return a reply:
def handle_event("something", _, socket) do
socket =
socket
|> assign(a: :something)
|> update(:b, fn x -> x + 1 end)
{:reply, %{b: socket.assigns.b}, socket}
end
:noreply is literally telling the caller of the callback “there’s no reply to send for this one”. That’s not a state transformation.


















