In the previous article focused on live_redirect
, we’ve seen how in Phoenix LiveView we can change the URL without changing the location or refreshing the page. In this way we can keep the URL updated with the current page state, making easier for the user to bookmark or share it.
We are going to see how to refactor the code with live_link, making the code simpler and reducing the number of messages exchanged between our browser and LiveView.
Pictures example with live_redirect/2
Let’s consider the LiveView Pictures page example, and see how, in this case, is convenient to use live_link/2
instead of live-redirect/2
.
In this example we have a list of thumbnails. When we click on a thumbnail, LiveView changes the URL and updates the page showing the full-size image.
defmodule DemoWeb.PicturesLive do
...
def render(assigns) do
~L"""
...
<%= for {id, pic} <- pictures do %>
<div class="column"
phx-click="show"
phx-value="<%= id %>">
<%= pic.author %>
<img src="<%= picture_url(pic.img, :thumb) %>">
</div>
<% end %>
...
"""
end
end
Each thumbnail element has phx-click="show"
and phx-value="<%= id %>"
attributes. In this way when we click a thumbnail the "show"
event is sent to the server along with the picture id.
def handle_event("show", id, socket) do
{:noreply, live_redirect(socket, to: Routes.live_path(socket, DemoWeb.PicturesLive, id))}
end
The LiveView process handles this event with handle_event("show", id, socket)
function, sending a live_redirect
message back to the browser.
Inspect LiveView messages
Let’s see better what happens, checking the messages exchanged between the browser and Phoenix.
I’m using the Chrome inspector, but with other browsers should be similar.
We open the inspector, we select the network tab and clicking WS
we show only the WebSocket connections. Refreshing the page we now see the WebSocket connection used by Phoenix LiveView and clicking on it we can see the messages exchanged between the browser and LiveView.
Clicking on a thumbnail we see four messages
[...,"event",{"type": "click", "event": "show", "value":"XesILKdmkwM"}]
[...,"live_redirect",{"kind": "push", "to": "/pictures/XesILKdmkwM"}]
- When clicking a thumbnail, the browser sends a
"show"
event message to LiveView. - Phoenix sends back a live_redirect message with the new
URL
and the LiveView front-end javascript library changes the URL to the new one usinghistory.pushState()
.
[...,"link",{"url":"/pictures/XesILKdmkwM"}]
[...,"phx_reply",{"response":{"diff": {...}}}]
- After changing the URL, the browser sends a message back to the server with the new URL.
- LiveView processes this message with
handle_params/3
, renders the new page and sends back a response with the differences to apply on the page.
This back and forth of messages is redundant – we can avoid the first two messages (click and live_redirect) with live_link
.
live_link
By using live_link
we don’t need to handle the click event ourself. We can then remove the two attributes, phx-click
and phx-values
, along with the handle_event("show", id, socket)
function.
defmodule DemoWeb.PicturesLive do
def render(assigns) do
...
<%= for {id, pic} <- pictures do %>
<%= live_link to: Routes.live_path(@socket, DemoWeb.PicturesLive, id) do %>
<div class="column">
<%= pic.author %>
<img src="<%= picture_url(pic.img, :thumb) %>">
</div>
<% end %>
<% end %>
...
end
end
We wrap our thumbnail tag with live_link
and use the same Routes.live_path/3
function as we did with live_redirect
– since we are inside a LiveView template, we just need to use @socket
instead of socket
.
We see how in this way the code becomes simpler and using the browser inspector, we also see that for each click we now have just two messages.
[...,"link",{"url":"http://localhost:4000/pictures/XesILKdmkwM"}]
[...,"phx_reply",{"response":{"diff": {...}}}]
With live_link, the browser changes immediately the URL without sending any click event (like we did before). Once changed, the new URL is sent to the server which re-renders the page and sends back a message with the differences to apply.
When using live_link
and when live_redirect
?
So, when to use live_link
and when live_redirect
?
In the Pictures example, the user interacts with the frontend clicking the links. It’s clear that live_link
is the right choice – it makes the code simpler and we get less exchanged messages.
In the animated URL example though, there is no user interaction (apart from starting/stopping the animation). Every 100 milliseconds the server tells the browser to change the URL, so in this live_redirect
is the way to go.