coen.bakker

coen.bakker

Alex Korban recently wrote an article called “Thoughts on Elixir, Phoenix and LiveView after 18 months of commercial use”, where he mentions that he avoids using live components whenever possible.

Live components are best avoided if possible, in my view.

There is a discussion of his article on Hacker News. Here Jose Valim agrees with him on his point about live components.

You are 100% correct on functional components vs live components. I will make it clearer in the docs the former should be preferred

The live component docs indeed include a short section about when to use functional components or live components.

Generally speaking, you should prefer functional components over live components, as they are a simpler abstraction, with a smaller surface area. The use case for live components only arises when there is a need for encapsulating both event handling and additional state.

However, I still don’t fully understand the rational behind choosing the one or the other.

For example, what does it mean for something to have a smaller surface area, in the context? And why is smaller better?

And why should live components exclusively be used when there is a need for event handling AND additional state?

What are the (hidden) costs of using live components, that make them something to avoid?

One reason I have been used live components is to make my code simpler to understand and easier to reason about, by encapsulation event handling and state. However, in some cases my code did not improve as much as I expected in that regard, partly because of the extra message handling between the root live view and the live component.

Showing Posts 1 to 7

w0rd-driven

w0rd-driven

Where things splinter is when you want to use PubSub. That relies on handle_info callbacks, which are so far only available close to the process or LiveView.

For a simple count badge, it was easier for me to use a functional component the LiveView handled state for. It ended up being 3 separate counts but I had less mental load with less oddities. My mental model for a badge counter is to init the record count from the database then use PubSub to increment that count.

I had problems understanding how to do that with update of LiveComponent in the mix. I wanted the state of each count with the component because colocating that state made sense. Marshalling messages through handle_info made less sense to me but I may be missing the plot on that.

I would say there is a place for a cheatsheet, checklist, or flow chart diagram that’s like “If you want PubSub, you try X with Y.”

cmo

cmo

I have this SQL query builder component. At some point I wanted to use it on a couple of other pages. It uses url query params and all the events were handled in the liveview. I went with keeping it as a function component and adding the params and event handling to the parent liveviews with attach_hook. This kept all the behavior in a module and there is only one callback to implement in the module that uses it.

Pretty sure I looked into doing it as a live component but as you said, you end up having to send events back and forth and it can get out of hand for some use cases. It is especially pointless when there is no internal state or events.

Say you’ve got a calendar component. It can be in either day, week or month view, has to accept events for navigating back and forwards through time. Most of the events and state are internal. The parent only cares about the date picked. This can be a live component and the parent handles one event and passes one assign. The rest are internal. You’re unlikely to have more than one or two on a page so the overhead isn’t much of a worry.

coen.bakker

coen.bakker OP

Thank you. That is very helpful.

D4no0

D4no0

Agree, if you don’t need internal self-contained state, using a live component is not recommended.

We were using it with the eariler versions of liveview, as there was no other way to do things back then.

coen.bakker

coen.bakker OP

This is helping me thinking about code organization better. I found an example in the codebase of LiveBook of this approach (see the LivebookWeb.Confirm module). Potentially a game changer for me personally. I did not realize the full power of hooks

silverdr

silverdr

The use case for live components only arises when there is a need for encapsulating both event handling and additional state

This sounds like you could still do event handling EOR additional state w/o live components.

Does this mean that you handle events in functional component? Or rather that you handle them in whatever uses functional component(s) and update those from there?

Would like to make sure I understand correctly “both event handling and additional state”, with emphasis on BOTH and AND.

Also – is there any difference between “function component” and “functional component” in Phoenix parlance?

rhcarvalho

rhcarvalho

I think not, just spelling. Function/functional components are functions that take a single argument assigns map and return a HEEx template:

def my_component(assigns) do
  ~H"""
  <h1>hello</h1>
  """
end

The latter. The former is not possible, as those are only functions. But events (in a LiveView or LiveComponent module) can mutate the assigns and change tracking will take care of updating whatever state changed in the function component, send the diff to the client and patch the DOM.

The emphasis on both is to guide people not to overreach to a more complicated solution. LCs have their space for organizing “too complex” LVs and for optimizing diff payloads. But they also add complexity, force you (and team) into understanding more pieces and how they interact.

If you only need to handle events, you can do so in a LV. If you only need to build reusable components that render based on assigns, that’s what FC help you compose.

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews