I’ve got a basic counter in LiveView where you click on a button and the counter increments by one. I’ve got a GenServer
that broadcasts the counter value to all the processes(?) —that message is broadcast to the processes first, right? Correct me please, if I’m wrong— in every 5 seconds or so, and then I handle this info to push an event to the client. On the client side I basically check whether the counter value on the page is ahead of the value that was broadcast, if so I basically don’t do anything. Otherwise I set the new counter value that was broadcast.
My problem is that, since I am using the state in the socket I also need to update the value in socket.assigns
, otherwise after the broadcast even though the counter value on the page changes the actual value of the counter in socket.assigns
doesn’t change. It’ll be clear with the code I think:
# counter_live.ex
# This is where I handle button clicks, to increment the counter value
@impl true
def handle_event("inc", _session, socket) do
Task.start_link(fn -> Counter.increment() end)
{:noreply,
socket
|> update(:counter_value, &(&1 + 1))
}
end
# This is where I handle the broadcast
@impl true
def handle_info(%{event: "update_counter_value", payload: payload}, socket) do
{:noreply,
socket
|> assign(payload)
|> push_event("update_counter_value", payload)
}
end
Respective leex
file:
<!-- counter_live.html.leex -->
<section>
<div id="counter">
<span id="counter-value" class="counter-value" phx-hook="counterUpdated"><%= @counter_value %></span>
<div><%= link "Increment", to: "#", phx_click: "inc", class: "button" %></div>
</div>
</section>
As you see above, in handle_info
function if I don’t use assign
since the value in the socket doesn’t change on the next button click the value will be back to the old value in socket.assigns
which you can see below.
If I use assign
and push_event
both at the same time then there’s a glitch in the UI where you can basically see the value going back to the old one and then JS updates it back to the broadcast value, which is annoying to see. I tried to record it which you can see below hopefully.
How can I handle this situation better? Basically I need to update socket.assigns
without triggering a diff pushed to the client (so only JS handles the UI update) but that’s not possible I’m told.