Dear Phoenix users,
I have a Phoenix umbrella project which uses LiveView (Phoenix 1.4.15 and LiveView 0.8.1). It contains a live view which has regular assigns that are updated approximately every 5 seconds and a graph (dygraphs JS) whose data is loaded with the press of a button (and might be updated at later time but is not for the moment).
The problem is that, once the button has been pressed and the data loaded, every time the other assigns are updated, the “updated” hook for the graph is called even if the graph data has not changed.
I made a minimal working example to check the problem without the rest of the code base and it is still present. The frequency of refresh has been set to 1 second. You can see on the screenshot that the Google JS console indicates that the updated message has been printed a total of 36 times instead of just one time, just after the press of the “update” button.
The question is : why does the update of @x
(and not @values
) leads to a call of the updated
hook ?
The problem looks like LiveView updated hook problem but the versions of the software are different. Maybe I should have posted this question as a reply to the previous post even if it doesn’t answer the OP question.
TIA
The relevant edited code is included below.
app.js
let graph = null;
let Hooks = {};
Hooks.chart = {
mounted() {
console.log("mounted");
},
updated() {
console.log("updated");
const data = JSON.parse(this.el.dataset.values);
if (graph === null) {
const div = this.el;
graph = new Dygraph(div, data, {
labels: ["x", "y"],
legend: 'always',
connectSeparatedPoints: true,
labelsDiv: "legend",
});
} else {
graph.updateOptions({ 'file': data });
}
}
}
...
let liveSocket = new LiveSocket("/live", Socket, { hooks: Hooks, params: { _csrf_token: csrfToken } });
...
Module PhxLv1Web.TestLive
(file test_live.ex
)
def render(assigns) do
Phoenix.View.render(PhxLv1Web.TestView, "test.html", assigns)
end
def mount(_params, _session, socket) do
if connected?(socket) do
Process.send_after(self(), :update, 1000)
end
{:ok, assign(socket, x: 0, values: nil)}
end
def handle_event("update", _value, socket) do
IO.puts "update"
values = (1..100) |> Enum.map(fn i -> [i, :rand.uniform(100)] end)
{:noreply, assign(socket, :values, values)}
end
def handle_info(:update, %{assigns: %{x: x}} = socket) do
Process.send_after(self(), :update, 1000)
{:noreply, assign(socket, :x, x+1)}
end
Template test.html.leex
<p>x = <%= @x %>.</p>
<button phx-click="update">update</button>
<div id="legend"></div>
<div id="graph" phx-update="ignore" phx-hook="chart" data-values="<%= Jason.encode!(@values) %>"></div>