What Is Phoenix LiveView?
Phoenix LiveView lets you build rich, real-time user interfaces in server-rendered Elixir, without writing client-side JavaScript frameworks like React or Vue. After an initial HTTP render, LiveView upgrades the connection to a persistent WebSocket; from then on, only minimal, diffed HTML patches are sent to the browser whenever server-side state changes, and Phoenix's own JavaScript client (phoenix_live_view.js) applies those patches to the DOM.
Cricket analogy: LiveView is like a stadium's giant screen that updates live with every ball, giving fans a real-time experience without them needing to refresh anything themselves.
The LiveView Lifecycle: mount, render, and handle_event
A LiveView module implements mount/3, which sets up initial socket.assigns (the view's state) and is called once for the initial HTTP request and again when the WebSocket connects. render/1 (or a colocated .html.heex template) declares the HTML based on current assigns using HEEx syntax with <%= @count %> interpolation. handle_event/3 responds to client-triggered events (like phx-click="increment"), typically updating assigns with assign/3 or update/3, which triggers a re-render and a diffed patch sent over the socket.
Cricket analogy: The mount/3 callback is like the toss at the start of a match — it sets up the initial state (who's batting) before any deliveries are bowled.
defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, assign(socket, count: 0)}
end
def render(assigns) do
~H"""
<div>
<p>Count: <%= @count %></p>
<button phx-click="increment">+1</button>
</div>
"""
end
def handle_event("increment", _params, socket) do
{:noreply, update(socket, :count, &(&1 + 1))}
end
endReal-Time Updates with PubSub
For updates that originate outside a single user's interaction — like a new comment posted by another user — LiveView processes subscribe to topics via Phoenix.PubSub.subscribe/2 in mount/3, and any process can broadcast a message with Phoenix.PubSub.broadcast/3. The subscribed LiveView's handle_info/2 callback receives the broadcast message, updates its assigns accordingly, and Phoenix automatically re-renders and pushes the diff to that specific connected client — enabling multi-user real-time features without any custom WebSocket plumbing.
Cricket analogy: Phoenix PubSub broadcasting a score update is like the stadium announcer relaying a wicket to every stand simultaneously, so all fans learn it at once.
LiveView vs. Traditional SPAs
Choosing LiveView over a traditional single-page app built with a JS framework trades client-side complexity for server-side state and network chattiness: there's no separate JSON API to design and version, and business logic lives in one place (Elixir), but every user interaction round-trips to the server over the WebSocket, meaning it's less suited for offline-first apps or scenarios with very high client-side interactivity per keystroke (though phx-debounce and JS hooks mitigate much of this).
Cricket analogy: Choosing LiveView over a traditional SPA is like choosing a live radio commentary feed over reading a printed scorecard you have to manually refresh.
LiveView's phx-click, phx-change, and phx-submit bindings cover most interactivity declaratively, but for cases needing real client-side behavior — like integrating a JS charting library or focusing an input — LiveView JS Hooks let you attach a JavaScript object with lifecycle callbacks (mounted, updated, destroyed) to a DOM element via phx-hook, bridging server state and client-only behavior cleanly.
- LiveView renders UI server-side and upgrades the initial HTTP connection to a persistent WebSocket.
- mount/3 initializes socket.assigns and runs once for the HTTP request and again for the WebSocket connect.
- render/1 (or a .html.heex template) declares markup based on current assigns using HEEx syntax.
- handle_event/3 responds to phx-click/phx-change/phx-submit bindings, updating assigns and triggering a diffed re-render.
- Phoenix.PubSub.subscribe/2 and broadcast/3 enable multi-user real-time updates via handle_info/2.
- LiveView trades a separate JSON API and client framework for server-rendered state and WebSocket round-trips.
- JS Hooks (phx-hook) bridge server-driven state with client-only JavaScript behavior when needed.
Practice what you learned
1. What connection type does LiveView upgrade to after the initial HTTP render?
2. How many times does mount/3 run for a typical LiveView page load?
3. Which callback handles a Phoenix.PubSub broadcast received by a LiveView?
4. What is the purpose of a phx-hook attribute?
5. What is a key tradeoff of choosing LiveView over a traditional JS-framework SPA?
Was this page helpful?
You May Also Like
Phoenix Framework Basics
An introduction to Phoenix's router, controllers, contexts, and plug pipeline — the core building blocks of a Phoenix web application.
Ecto and Databases
How Ecto's Repo, Schema, Changeset, and Query modules work together to safely model, validate, and query data in Elixir.
Testing with ExUnit
A practical guide to writing, organizing, and running tests in Elixir using ExUnit's assertions, fixtures, tags, and doctests.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics