Live Sessions in Phoenix LiveView: Reducing navigation time between LiveViews

Deankinyua

Deankinyua

2 days ago

0 comments

The main idea behind live sessions is to reduce navigation time when navigating a group of routes. Normally what happens when navigating between LiveViews is a HTTP request gets sent to the server, a connection is made and the new LiveView is mounted in place. However, this forces a full page reload making the user experience not so good.

With Live Sessions, that HTTP request doesn’t have to be sent as we can do a live_redirect over the existing web socket connection. If the LiveViews are not in the same live session a full page reload will be done instead.

Take the following as an example:

    scope "/", ElixirDropsWeb do
    pipe_through [:browser, :require_authenticated_user]

    live_session :require_authenticated_user do
      live "/profile", UserDropLive.Index, :index
      live "/notifications", NotificationLive.Index, :index

      live "/drops/:short_id/edit", UserDropLive.Index, :edit
      live "/drops/new", UserDropLive.Index, :new
    end
  end

Let’s then say we have this link in the notification page:

            <.link navigate={~p"/profile"}>
                My drops
              </.link>

Instead of our request flowing through the pipeline as a normal HTTP request would, it goes through the live session and that makes it much faster hence a better user experience. What if the profie page requires some kind of authentication to identify the current_user ?

That’s where on_mount hooks come into place. These are just functions that will either halt or continue the mounting process. For example, If the hook finds out that the person viewing the page is a guest, the :ensure_authenticated hook halts the connection from proceeding further.

    live_session :require_authenticated_user,
      on_mount: [
        {ElixirDropsWeb.UserAuth, :ensure_authenticated},
        {ElixirDropsWeb.UserAuth, :assign_current_user},
        {ElixirDropsWeb.NavbarSearchHook, :navbar_search}
      ] do
      live "/profile", UserDropLive.Index, :index
      live "/notifications", NotificationLive.Index, :index

      live "/drops/:short_id/edit", UserDropLive.Index, :edit
      live "/drops/new", UserDropLive.Index, :new
    end

It looks like this:

 # the auth module 
  def on_mount(:ensure_authenticated, _params, session, socket) do
    socket = assign_current_user(socket, session)

    if socket.assigns.current_user do
      {:cont, socket}
    else
      socket =
        socket
        |> Phoenix.LiveView.put_flash(:error, "You must log in to access this page.")
        |> Phoenix.LiveView.redirect(to: ~p"/")

      {:halt, socket}
    end
  end

Comments (0)

Sign in with GitHub to join the discussion