LiveView

Modern web applications usually render views in the browser using JavaScript. LiveView renders HTML on the server and pushes changes to the client through diffs over WebSockets.

A Counter

defmodule App1Web.CounterLive do
  use Phoenix.LiveView

  def mount(_params, _session, socket) do
    {:ok, assign(socket, :count, 0)}
  end

  def handle_event("increment", _, socket) do
    {:noreply, update(socket, :count, &(&1 + 1))}
  end

  def render(assigns) do
    ~H"""
    <div>
      <p>Count: { @count }</p>
      <button phx-click="increment">+</button>
    </div>
    """
  end
end

Add a routing rule under scope "/":

live "/counter", CounterLive

The counter is now ready at http://localhost:4000/counter.

Anatomy of a LiveView Component

The LiveView component is a module with specific functions like mount, render and handle_event. Similar to React's class component, those are called lifecycle callbacks, as they are invoked at different stages.

  • mount: Invoked once when the component is first added to the page or the LiveView process is started. It's used to initialize the component's state (assigns).

  • handle_event: Handles events originating from the client (e.g., button clicks).

  • render: Called to generate HTML.

  • update: Called whenever the assigns passed to the component from its parent LiveView change. It's an opportune place to update the component's internal state based on the new assigns.

A Rough Comparation with React

Life Cycle Callbacks:

LiveView ComponentReact Class Component
mount(params, session, socket)componentDidMount()
handle_event(event, params, socket)custom functions
render(assigns)render()
update(assigns, socket)componentDidUpdate(prevProps, prevState)

Event Handling:

LiveView ComponentReact Class Component
phx-clickonClick
phx-changeonChange

State Management:

LiveView ComponentReact Class Component
assign(socket, state)this.setState(state)
update(socket, key, fn)this.setState(fn)

Thoughts on LiveView

The ultimate goal of LiveView is to create dynamic server-rendered applications without writing JavaScript.

It is kind of a unique and intereting solution from Phoenix.

  • States are kept on the server, not in the browser, rendering is also done on the server.
  • After rendering, a diff with previous rendering result is done and only the diff is sent to the browser, in order to minimize the payload.

Why is the idea not adapted in other frameworks?

  • It relies on WebSocket, which is cheap in Phoenix but a luxury for a lot of other frameworks.
  • It's a back-end oriented solution, the JavaScript community is front-end centric, and LiveView solves a problem that they don't have.

LiveView is a good fit for

  • Chats, monitoring(real-time updates)
  • Dashboards, admin panels(limited number of concurrent users, relative simple interaction)
  • Developers with limited front-end skills

Not suitable for

  • UI-heavy apps with complex states
  • Apps with extreme high-concurrency usage
  • Mobile-first apps on unstable networks, or apps with offline usage