Announcing Dash Bio 1.0.0 🎉 : a one-stop-shop for bioinformatics and drug development visualizations.

Dash component keeps updating on its own

Hello, Dash Community.

I am developing a data visualize program as a school project. Currently a have a simple layout: data file dropdown chooser, some checkboxes, a slider to choose the threshold and a graph, that depends on these properties. Code :

app.layout = html.Div([


    # Choosing dataset
    html.Label('Dataset'),
    dcc.Dropdown(
        id='dataset',
        ...
    ),

    # With or without nonfrauds
    html.Label('Nonfrauds'),
    dcc.Checklist(
        id='nonfrauds',
        options=[
            {'label': 'With Nonfrauds', 'value': 'Yes'},
        ],
        values=['Yes']
    ),

    # Highlights actual frauds
    html.Label('Highlight actual frauds'),
    dcc.Checklist(
        id='highlight',
        options=[
            {'label': 'Highlight', 'value': 'Yes'},
        ],
        values=[]
    ),

    # Threshold slider
    html.Label('Threshold'),
    dcc.Slider( ...
    ),
    html.Div(id="threshold-selected"),

    # Update button
    html.Button("Reload", id='reload'),


    # Graph
    html.Label("Graph"),
    html.Div([
        dcc.Graph(
            id='graph',
            figure=go.Figure(
                data=get_markers(raw_data, actual_results=True),
                layout=graph_layout,
            ),
        ),
    ], id="graph-container"),

], style={'width': '80%'})

Now, the graph takes data from the function that is tested and works OK. I use a callbacks on the button to update the graph, with respect to states of the properties. Here is the callback for the graph:

@app.callback(Output('graph-container', 'children'),
              [Input('reload', 'n_clicks')],
              [State('dataset', 'value'),
               State('threshold', 'value'),
               State('nonfrauds', 'values'),
               State('highlight', 'values')]
              )
def update_graph(n_clicks, dataset, threshold, with_non_frauds, highlight):
    print(n_clicks)
    new_data = pd.read_csv("data/" + dataset)
    data = get_markers(new_data, threshold=threshold,
                       with_non_frauds=len(with_non_frauds) != 0,
                       actual_results=len(highlight) != 0)
    return html.Div([
        dcc.Graph(
            id='graph',
            figure=go.Figure(
                data=data,
                layout=graph_layout
            )
        )
    ], id="graph-container")

I run the server on my local, so it gets started and executed as following:
app = dash.Dash(“Semestralka”, external_stylesheets=external_stylesheets)
app.run_server(port=8051, debug=True)

The problem is, that when I start the server, it keeps on updating on its own, without me clicking the button. I’ ve added the
print(n_clicks)

line to see, if the update function actually gets called. And it turned out that yes, it does, even if I don’t press the button, so the console output is following:

127.0.0.1 - - [23/Dec/2018 11:37:23] "POST /_dash-update-component HTTP/1.1" 200 -
None
127.0.0.1 - - [23/Dec/2018 11:37:24] "POST /_dash-update-component HTTP/1.1" 200 -
None
127.0.0.1 - - [23/Dec/2018 11:37:28] "POST /_dash-update-component HTTP/1.1" 200 -
None

I would appreciate any clue or piece of advice. You can see my whole code on GitHub here:

Try to set your code in update_graph behind an if-condition like:

def update_graph(n_clicks, dataset, threshold, with_non_frauds, highlight):
    if n_clicks:
        # execute code ...
1 Like

Thank you for answer. I’ve added this condition, but now it automatically updates after I once click the button

In your callback that sets the children of graph-container you are returning a html.Div with id='graph-container'. Dash is then firing the callback to populate the graph-container, which creates a new graph-container which fires the callback etc.

I managed to fix it by changing

return html.Div([
        dcc.Graph(
            id='graph',
            figure=go.Figure(
                data=data,
                layout=graph_layout
            )
        )
    ], id="graph-container")

to

return dcc.Graph(
    id='graph',
    figure=go.Figure(
       data=data,
       layout=graph_layout
    )
)
1 Like

Wonderful! Thank you very much.

html.Div([… will give an error like that…

OK sort of a newbie question here. I see that returning an dcc.Graph is better than returning the entire html.Div. I get that. What I do NOT get is that i have some basic misunderstanding about your answer: “… Dash is then firing the callback to populate the graph-container…” My question is WHY does dash fire a callback when the output is updated? If it was an input I would totally get it, but it isn’t. So just trying to address a basic misconception I may have. Is there some OTHER callback (other than update_graph(…) shown that is causing reload button to trigger again?