Hello friends,
I’ve got the following snippet on a .heex template in my LiveView for rendering a board for a game:
<div class='board'>
<%= for y <- 1..100 do %>
<%= for x <- 1..100 do %>
<div class={Map.get(@rendered_board, {x,y})}></div>
<% end %>
<% end %>
</div>
The rendered_board
assign is a Map with keys from {1,1} to {100,100} and values like :empty, :dirty, :player etc. The mount function of my liveview initializes the rendered_board assign and there’s an event handler that is executed when the player is moved. So this event handler will change like 1 element (i.e the player moved 1 square up). So the return of the event handler will be something like:
{:noreply, socket |> Map.put(socket.assigns.rendered_board, {1,1}, :new_value)}
Notice that the rendered_board assign is changed but only 1 element of that assign is really changed.
My problem is that when that happens, the liveview pushes all class elements to my socket (not only the changed ones) ! This results in a payload of like 162kb. The payload is similar to this:
["4","268","lv:phx-Fr94ffyVaEgkhA4j","phx_reply",{"response":{"diff":{"2":{"0":{"0":"{86, 43}","2":"%{1 => %{pos: {86, 43}, socket_id: "phx-Fr94ffyVaEgkhA4j"}}",
"3":{"d":[[{"d":[["square empty"],["square dirt"],["square dirt"],["square dirt"],["square dirt"],
["square dirt"],["square dirt"],["square dirt"],["square dirt"]
...
thousands more elements
...
,["square dirt"],["square dirt"]],"s":0}]],"p":{"0":["\n <div class=\"","\"></div>\n"]}}}}}},"status":"ok"}]
Is there a way to have the correct behavior ? I.e I wanted live view to push only the changed elements and leave the others alone. I tried assigning ids to the board divs but no luck. Is what I want even possible with LiveView ? If it ain’t then I could try a client-side solution but I’d rather avoid JS
Kind regards,
Serafeim