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
Tweet