We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
What if mount had separate function heads for (dis)connected render?
If you’ve spent any time reading or writing LiveView, you have undoubtedly seen code that looks a lot like this:
def mount(params, session, socket) do
if connected?(socket) do
# connected mount
else
# disconnected mount
end
end
Right away the mount/3
callback is checking to see if the socket is connected. Generally it’s so that the “heavy lifting” of loading items from the database or making network calls is only done once the websocket connection is established. This makes sense because it would be wasteful to make all of those calls just to throw away the results and do it all over again once the websocket connection is established.
But something never sat quite right about the way it was implemented. After all, Elixir heavily promotes pattern matching and it’s one of the things I love most about the language.
For a while I assumed that connected?/1
was implemented as a function and not a guard because it needed to do some sort of analysis at runtime to determine whether or not there was an active websocket connection.
One day I decided to finally peek under the covers and see for myself:
# phoenix_live_view.ex
def connected?(%Socket{transport_pid: transport_pid}), do: transport_pid != nil
Nope. The implementation of connected?/1 is a one line nil check.
Now we must ask the question: Can we make this a guard?
Turns out, we can! And it’s pretty simple, too:
defguard is_connected?(socket) when socket.transport_pid != nil
We can make this guard available to all of our liveviews by simply dropping the line inside of our live_view
definition inside app_web.ex
:
def live_view do
quote do
use Phoenix.LiveView,
layout: {JohnElmLabsWeb.Layouts, :app}
unquote(html_helpers())
# Add the line here:
defguard is_connected?(socket) when socket.transport_pid != nil
end
end
Now we can break apart our disconnected and connected mounts with ease:
def mount(params, session, socket) when is_connected?(socket) do
# Connected mount
end
def mount(params, session, socket) do
# Disconnected mount
end
And that’s all it takes. Will you use this in your LiveViews going forward? I know I sure will.
Build an AI Powered Instagram Clone with LiveView is on sale now!