Communication between live components?

EDIT: this is my opinion and not an overall position of the Phoenix team about LiveComponents. Give it a try and evaluate it for yourself.

IMO LiveComponents are one of the most overused features of LiveView. It makes sense from a historical sense, they were one of the first abstractions to be added, but today we have function components, LV hooks, JS commands, and others which can be better suited for creating abstractions.

For example, before Phoenix v1.7, everyone used LiveComponents to create modals, and then the Phoenix team showed it could be done with plain function components plus JS commands. Given function components are the simplest abstraction, then they should be the first choice.

If they are not enough, I’d say hooks are more powerful and provide a better foundation than LiveComponents for building new abstractions. For example, imagine you are creating a “live table” with pagination and search. Most people would immediately design it as a LiveComponent for reuse, but I would rather introduce a LiveTable data structure and build on top of that. Something like this:

assign_live_table(socket, :posts, arg1, some_opt: ...)

And now, all of the state of the table is stored directly in the socket, which you can access and manipulate through additional functions. When it comes to rendering, you pass the table plus the name of any event you want dispatched, as if it was any other function component/html element:

<LiveTable.render table={@posts} row-click="some-event" />

Inside LiveTable.render, you can use JS commands to dispatch events and, if there are internal events, you can use attach_hook during “assign_live_table” to consume them.

This is precisely how streams and assign async are designed and implemented in LiveView itself.

We have tried this direction with couple of our Dashbit clients and, every time so far, it has led to better designs: components that are easier to use and tests. Of course, live components still have their use cases, especially when breaking down a LiveView into non-reusable parts, optimizing what goes over the wire, etc. I don’t know what is the best answer here, as we don’t have enough context, but I thought I would bring this other option to the table.

15 Likes