Hello,
I am playing with LiveView and I find the diff mechanism to be not very efficient with comprehensions, or I am doing something wrong.
Let’s say I have a 100x100 table where user can click a cell to select it.
It is represented just by list of lists and it is passed as assign to the live view template:
@impl true
def mount(_params, _session, socket) do
table =
for i <- 1..100 do
for j <- 1..100 do
"#{i},#{j}"
end
end
{:ok,
socket
|> assign(:selected_cell, nil)
|> assign(:table, table)
}
end
And rendered using comprehensions:
<table>
<%= for row <- @table do %>
<tr>
<%= for cell <- row do %>
<td phx-click="cell_clicked" {"phx-value-cell": cell]}>
<%= if @selected_cell == cell do %>
<b><%= cell %></b>
<% else %>
<%= cell %>
<% end %>
</td>
<% end %>
</tr>
<% end %>
</table>
Once the user clicks the cell, it marks the cell as selected, causing re-render:
@impl true
def handle_event("cell_clicked", %{"cell" => cell}, socket) do
{:noreply, assign(socket, :selected_cell, cell)}
end
The problem is that the size of diff being sent over web socket is 600 KB. It seems that it contains updated contents of the whole table. I’ve read the docs on how comprehensions are handled but the approach explained in the docs seems to be very limited. IMO it should be smart enough to update just the particular cell.
Is it how it is supposed to work or am I doing something wrong? Any workaround to avoid re-sending the whole table? Or maybe can you give any guidance on how the diff mechanism can be improved if this is on purpose?