user20230119
Is Using Nested LiveComponents and Process Dictionary an Antipattern in LiveView?
I’m currently working on a LiveView project where I have a fairly complex UI with nested components. Specifically, I’m using nested LiveComponents to represent hierarchical data structures. Additionally, I’m leveraging the Process Dictionary (Process.put/2 and Process.get/2) to store and retrieve some state, such as the currently selected child entity.
Here’s a simplified example of what I’m doing:
# LiveComponent
~H"""
...
<.button phx-click="select_child" phx-value-id={@entity.id}>Select</.button>
<.button phx-click="link_child" phx-target={@myself} phx-value-path="parent">Link</.button>
...
"""
def handle_event("link_child", %{"links" => path} = params, socket) do
id = case Process.get(:selected_child) do
nil -> ""
child -> child.id
end
socket =
with {:ok, entity} <-
MyApp.Entity.update_entity_links(socket.assigns.entity,%{path: path |> List.wrap(), value: id})
do
socket |> assign(:entity, entity)
else
{:error, error} ->
error |> dbg()
socket
end
{:noreply, socket}
end
# LiveView
def handle_event("select_child", %{"id" => id}, socket) do
socket =
with {:ok, child} <- MyApp.Entity.get_entity_by_id(id) do
Process.put(:selected_child, child)
socket |> assign(:selected_child, child)
else
{:error, error} ->
error |> dbg()
socket
end
{:noreply, socket}
end
The nested LiveComponents are used to render and manage parts of the UI, and the Process Dictionary is used to share state between different parts of the LiveView. Are there any pitfalls I should be aware of, or alternative approaches you’d recommend?
Most Liked
garrison
A simple answer would be that it’s not idiomatic in LiveView. The comment above points out the change tracking issues.
There are push-based and pull-based reactive systems (really it’s more of a spectrum). LiveView is more on the push side of things - assigns are marked dirty at assign() time and then the dynamics are re-sent in a batch computation. The point being: diffing actually happens when you call assign(), not at render time. In React for example it’s closer to the other way around (though not exactly - they are both somewhere in the middle of the “spectrum”).
If you start storing state outside of the LiveView system you are playing with fire. Technically in the examples from the OP the assigns are not actually used in the template so it should work, but in practice you often want to update your UI based on what item is selected. If you are passing data around via the process dictionary you can no longer propagate information about which assigns are dirty in each render, and the UI will no longer update properly. It’s bad practice to go down this path.
I’m sure there are situations where if you know exactly what you’re doing you could get away with this, but the OP is asking whether it’s an antipattern, and the answer to that is yes, absolutely.
And I know you’re probably aware of this, but for anyone new who’s happening across this thread: we generally try to avoid using the process dictionary in general. It’s an escape hatch which is there for when you really need it.
garrison
Nesting LiveComponents is fine.
Using the process dictionary like that, though, is a very bad idea. You should pass state down explicitly through assigns. If you need to send information between components you can use send() and send_update().
Schultzer
Why is it a bad idea?
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








