Today I Learned

A Hashrocket project

Ready to join Hashrocket? Find Openings here and apply today.

Preloading data for Phoenix LiveView components

One of the most common problems in web development is N+1. Graphql has taught me the DataLoader pattern and since then I never had to worry about N+1 as long as I kept using that pattern.

With Phoenix LiveView you don’t need to think about APIs anymore but I’m glad that it has support for preloading data kind of the same way as if it was a DataLoader. You can define a preload function that will receive a list of all the assigns so you can preload all the data needed for multiple components in one single batch before they are mounted. Here is the sequence of a component lifecycle:

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

On this example only one SQL query is made to load all products by id:

@impl true
def preload(list_of_assigns) do
  product_ids = Enum.map(list_of_assigns, & &1.product_id)

  products =
    from(p in Product, where: p.id in ^product_ids, select: {p.id, p})
    |> Repo.all()
    |> Map.new()

  Enum.map(list_of_assigns, fn assigns ->
    Map.put(assigns, :product, products[assigns.product_id])
  end)
end
Looking for help? At Hashrocket, we 💜 Elixir! From our many Elixir client projects, to sponsoring the Chicago Elixir Meetup, to the source code for this application, we are invested in this community. Contact us today to talk about your Elixir project.