Problem with client-side js function

Good day everyone!
I try to rewrite my original callback that updates graph components through time (and it works just fine) to the client-side callback. I don’t really know JS, so I’ve just tried to write my JS code regarding similar examples. The problem is that after the first initial update - my graph becomes completely cleared and such an error appears:

I suggest, maybe I’ve made some kind of mistakes in my js file, but I don’t really see them… I would be very happy if you can spot where am I wrong!

My original Python callback

@callback(
    Output("heatmap", "figure"),
    Input("interval-graph-update", "n_intervals"),
    State("x_store", "data"),
    State("y_store", "data"),
    State("z_store", "data"),
    State("heatmap", "figure"),
    State("y_scatter", "data"),
    State("yz_scatter", "data"),
    State("x_scatter", "data"),
    State("xz_scatter", "data"),
    Input("x_click", "data"),
    Input("y_click", "data"),
    Input("heatmap", "clickData"),
    State("line-switches", "on"),
)
def update_graph(
    i,
    x,
    y,
    z,
    fig,
    y_scatter,
    yz_scatter,
    x_scatter,
    xz_scatter,
    x_click,
    y_click,
    click,
    line_switch,
):
    triggered_id = ctx.triggered_id
    if i == 0:
        raise PreventUpdate

    if x_click is None:
        fig["layout"]["shapes"][0].update({"visible": False})
        fig["layout"]["shapes"][1].update({"visible": False})
    else:
        fig["layout"]["shapes"][0].update({"visible": line_switch})
        fig["layout"]["shapes"][1].update({"visible": line_switch})

    if triggered_id == "interval-graph-update":
        fig["data"][0].update({"x": x, "y": y, "z": z})
        return fig
    elif triggered_id == "heatmap":
        fig["data"][1].update({"x": yz_scatter, "y": y_scatter})
        fig["data"][2].update({"x": x_scatter, "y": xz_scatter})
        fig["layout"]["shapes"][0].update(
            {
                "x0": x_click,
                "x1": x_click,
            }
        )
        fig["layout"]["shapes"][1].update({"y0": y_click, "y1": y_click})
        return fig

My JS script in the /assets folder

window.dash_clientside = Object.assign({}, window.dash_clientside, {
  clientside: {
    refresh_graph: function (
      i,
      x_click,
      y_click,
      click,
      x,
      y,
      z,
      fig,
      y_scatter,
      yz_scatter,
      x_scatter,
      xz_scatter,
      line_switch
    ) {
      const triggered_id = dash_clientside.callback_context.triggered.map(
        (t) => t.prop_id
      );

      if (x_click === null) {
        fig["layout"]["shapes"][0]["visible"] = false;
        fig["layout"]["shapes"][1]["visible"] = false;
      } else {
        fig["layout"]["shapes"][0]["visible"] = line_switch;
        fig["layout"]["shapes"][1]["visible"] = line_switch;
      }
      if (triggered_id === "interval-graph-update") {
        fig["data"][0]["x"] = x;
        fig["data"][0]["y"] = y;
        fig["data"][0]["z"] = z;
        return fig;
      } else if (triggered_id === "heatmap") {
        fig["data"][1]["x"] = yz_scatter;
        fig["data"][1]["y"] = y_scatter;

        fig["data"][2]["x"] = x_scatter;
        fig["data"][2]["y"] = xz_scatter;

        fig["layout"]["shapes"][0]["x0"] = x_click;
        fig["layout"]["shapes"][0]["x1"] = x_click;

        fig["layout"]["shapes"][1]["y0"] = y_click;
        fig["layout"]["shapes"][1]["y1"] = y_click;
        return fig;
      }
    },
  },
});

Python implementation of this code

clientside_callback(
    ClientsideFunction(namespace="clientside", function_name="refresh_graph"),
    Output("heatmap", "figure"),
    Input("interval-graph-update", "n_intervals"),
    Input("x_click", "data"),
    Input("y_click", "data"),
    Input("heatmap", "clickData"),
    State("x_store", "data"),
    State("y_store", "data"),
    State("z_store", "data"),
    State("heatmap", "figure"),
    State("y_scatter", "data"),
    State("yz_scatter", "data"),
    State("x_scatter", "data"),
    State("xz_scatter", "data"),
    State("line-switches", "on"),
)

In your Python callback you have this

whereas you do not have something equivalent in JS, maybe this is intentionally but worth mentioning.

If you don’t want the callback to be triggered at startup, you could add prevent_initial_call=True

I think, that the problem is in the way how I change values in the dictionary. For instance, if I comment out all except refreshing values with the Interval component, it will not work too (the graph would stay constant through time). I’m confused about how I update my values in the dictionary, maybe I do it incorrectly in JS?

Try something like this from this topic (the newFig line)

app.clientside_callback(
    """
    function(drop_val, fig, init_val) {
        newFig = JSON.parse(JSON.stringify(fig))
        if (drop_val == 1.0) {
            newFig['data'][0]['z'] = init_val
        } else {
            newFig['data'][0]['z'] = init_val.map(element => element * drop_val)
        }
        return newFig
    }
    """,
    Output('graph', 'figure'),
    Input('drop', 'value'),
    State('graph', 'figure'),
    State('store', 'data'),
    prevent_initial_call=True
)

No, unfortunately, it doesn’t work :frowning: