This is something on the back of my mind as well, and these are my thoughts after having implemented an LiveView application for a hackathon this past weekend.
As all good answers, it depends. I’ll first explain a bit of what I did and how I structured it, and then we’ll discuss some use cases I came up with while tinkering with LiveView/Components.
Disclaimer: it’s my first experience with LiveView so I’m open to scrutiny/suggestions! Take this with a grain of salt
What I did was basically a full blown single-page-application with 5 screens. I used the LiveView layout to render a
live_component that contained the
live_redirect to 5 different LiveViews.
# Component that renders the live_redirects
defmodule MyAppWeb.NavComponent do
use GaminvestWeb, :live_component
def render(assigns) do
<%= live_redirect to: Routes.live_path(@socket, MyApp.PageOneLive) do %>
<% end %>
<%= live_redirect to: Routes.live_path(@socket, MyApp.PageTwoLive) do %>
<% end %>
<%= live_component @socket, MyApp.HeaderComponent, classname: "layout__header", page_title: @page_title %>
<%= @inner_content %>
<%= live_component @socket, MyApp.NavComponent, classname: "layout__navbar", page_title: @page_title %>
I feel that you should reach for a LiveComponent when you want to separate a complex piece of UI from the main LiveView and you need to share data between the main LiveView and the Component. I say this because the above could have been achieved without using LiveComponent at all through
render/2 as stated in LiveView docs, my most viewed and loved page of the weekend <3.
<%= render "header.html", assigns %>
<%= @inner_content %>
<%= render "navbar.html", assigns %>
Why did I use LiveComponent? Well, I overlooked this and LiveComponent just worked, so I moved on. But in hindsight, it made more sense to use
render/2 for this particular example. However, the advantage of using LiveComponent is it’s hability to handle events and have state!
Think of LiveComponents as a kind of function that encapsulates a complex piece of UI under a parent LiveView. They can be stateless or stateful, but they are always tied to a parent LiveView. This complicates things a little bit, since you can send data up to the parent.
Most of the time, you’ll want to pass data from the LiveView down to the LiveComponent. This is how I learned in React, and imo makes your interactions easier to reason about. However, unlike React, Phoenix gives you a “event bus” through PubSub! So you could trigger changes using PubSub and read those changes up in the parent LiveView. These are all documented in the LiveComponent docs.
If you’re familiar with React, you can think of LiveComponents as being React components. LiveComponents with an
:id are stateful, akin to React components that use
useState, and LiveComponents without an
:id are akin to “dumb” React components, that is, components with no state.
Tl;dr: IMO a LiveView should have one concern to worry about. Group functionality that is closely related domain-wise under a LiveView, and use LiveComponents to handle complex piece of functionality under your LiveView.
live_redirect means changing domains, i.e. is related to other LiveViews, and
live_patch means changing functionality in the same LiveView, i.e. is related to LiveComponents.