Navigation
Patch vs Navigate
What each navigation mode actually does to the socket
- Link
- handle_params
Key concepts
patch
and navigate
both keep the browser on the same
page without a full reload, but they do different things to the
LiveView process underneath: patch calls handle_params/3
on the LiveView that's already running; navigate mounts a brand new
one, in the same connection.
defmodule MyAppWeb.LinkDemoLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
# Stored in the process dictionary, not an assign, specifically so it
# survives a remount: every route in this app's router lives in the
# single default (unnamed) live session, so `navigate` reuses the same
# BEAM process even though it calls `mount/3` again from scratch.
mount_count = Process.get(:link_demo_mount_count, 0) + 1
Process.put(:link_demo_mount_count, mount_count)
socket = assign(socket, mount_count: mount_count, params_update_count: 0, current_path: "")
{:ok, socket}
end
def render(assigns) do
~H"""
<.react
name="LinkDemo"
currentPath={@current_path}
mountCount={@mount_count}
paramsUpdateCount={@params_update_count}
socket={@socket}
/>
"""
end
def handle_params(_params, uri, socket) do
%{path: path} = URI.parse(uri)
socket =
assign(socket,
current_path: path,
params_update_count: socket.assigns.params_update_count + 1
)
{:noreply, socket}
end
endHow it works
mount_count is stored in the process dictionary, not in
an assign, specifically so it survives a remount — every route in
this app's router lives in the single default (unnamed) live
session, so navigate reuses the same BEAM process even
though it calls mount/3 again from scratch.
Click "patch": the URL changes, params_update_count
goes up, mount_count
does not — same process, same
mount, only handle_params/3
ran again. Click "navigate": mount_count
goes up too — a fresh LiveView, reusing the
connection but not the state.