LiveComponent vs child LiveView

So I wanted to make sure to understand the different tradeoffs between LiveComponents and child LiveViews

If you have the need create a component that also needs state and handle events, you’ll need to reach for either a LiveComponent or a child LiveView.

The difference between them as far I as found out so far:

  • A LiveComponent runs in the parent LiveView process, whereas a child will run in it’s own process. This means that a crash in the LiveComponent crashes the parent. This is not the case for the child.
  • because a LiveComponent is not a process, it does not have handle_info. So if you need to interact with handle_info you’ll need to handle that in the parent.
  • A child LiveView can’t implement handle_params. I’m not sure how the lifecycle of a child LiveView works exactly.
  • You can’t pass assigns to a child LiveView easily. You can pass them via a session, or via sending messages I guess.
  • re-rendering of a child LiveView doesn’t happen automatically when the parent re-renders, even if the session data changes, no re-render is triggered.
  • When using a LiveComponent you’ll always need to pass phx-target to target the correct component. This means you might need to pass on the @myself to other components.

Can you fully encapsulate state/events in case you want to render it from multiple different parents?

I don’t think so, the parent always needs to know about handle_info in case of a LiveComponent.
And a child LiveView behaves completely differently regarding to passing assings and re-rendering.

Furthermore, when using LiveComponents you will need to pass on @myself down to all components that trigger any handle_event callbacks. Even if you nest your components only a little bit, this is a lot of passing this down.

When to choose a child LiveView over a LiveComponent?

I’m not sure I know good use cases.

Remarks?

Let me know where I’m wrong.

You can encapsulate the events by defining a function in the component’s module to attach the event handlers with attach_hook. That way you define it all once and just need to attach the hooks wherever the component is used.

def mount(...) do
  socket = 
    socket
    |> MyComponent.attach_hooks(...)

  {:ok, socket}
end

Never used a child liveview so nothing to add on that topic.

1 Like