terenceponce

terenceponce

How to use Phoenix 1.7 Streams on LiveComponent preload?

The recent Phoenix 1.7 came with Streams. The example given in the blog post was straightforward and easy to understand.

However, how would you use them when preloading a LiveComponent?

Given the example about preloading from the docs:

def preload(list_of_assigns) do
  list_of_ids = Enum.map(list_of_assigns, & &1.id)

  users =
    from(u in User, where: u.id in ^list_of_ids, select: {u.id, u})
    |> Repo.all()
    |> Map.new()

  Enum.map(list_of_assigns, fn assigns ->
    Map.put(assigns, :user, users[assigns.id])
  end)
end

Would it be possible to do it in the Map.put() section? Is it even possible to do streams when preloading?

Marked As Solved

codeanpeace

codeanpeace

This preloading example from the docs demonstrates how to avoid an n+1 query, which the stream example from the blog posts accomplishes by calling Blog.list_posts() that likely looks something like def list_posts(), do: Repo.all(MyApp.Post).

So in this case, preloading database resources into socket assigns may well be unnecessary/superfluous since these resources have already been added into the socket streams. And since one of the big advantages of streams is to offload storing of collections in memory on the server, I would think twice about about preloading and storing these same collections in memory on the server via socket assigns when using streams.

I haven’t tested it, but this could be one way of passing streams into multiple LiveComponents via assigns.

defmodule DemoWeb.PostLive.Index do
  use DemoWeb, :live_view

  alias Demo.Blog
  alias Demo.Blog.Post

  @impl true
  def mount(_params, _session, socket) do
    {:ok, stream(socket, :posts, Blog.list_posts())}
  end

  ...
end
# index.html.heex
<%= for post <- @streams.posts do %>
  <.live_component module={PostComponent} id={post.id} post={post} />
<% end %>

On another note, the following section of the Phoenix.LiveComponent docs on Preloading and update might help in understanding what @josevalim is saying.

So on first render, the following callbacks will be invoked:

preload(list_of_assigns) -> mount(socket) -> update(assigns, socket) -> render(assigns)

On subsequent renders, these callbacks will be invoked:

preload(list_of_assigns) -> update(assigns, socket) -> render(assigns)

Since you need the socket to pass into the stream, stream_insert, or stream_delete functions, only the mount and update LiveComponent callbacks can interact with streams.

Also Liked

josevalim

josevalim

Creator of Elixir

The main point is that preload does not know about streams. All the data in preload is copied to the socket in the update/2 callback. So that would be the place to insert data into the stream. If you give it a try, I can gladly review and provide pointers.

josevalim

josevalim

Creator of Elixir

The preload happens outside of the LiveComponent. You don’t really have access to the socket there. So for streams in live components, you can define it on mount, prepare the assigns on preload, and then load them into the stream on update.

josevalim

josevalim

Creator of Elixir

I just gave some pointers, @codeanpeace gave the proper and complete answer. :slight_smile:

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&amp;query=perfume&amp;page=2, I would like to get: ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New

Other popular topics Top

axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52673 488
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement