dash: [BUG] dcc.Location callback fires twice IDENTICALLY

As far as I can tell, this flavor of the “duplicate dcc.Location callback” issue (#883) hasn’t been documented yet. When I run a multipage app, reloading the page fires the callback twice with the same href / pathname / search payload. This is distinct from the other issue of having the callback return None and then returning the proper value(s).

import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import dash
import urllib

navbar = dbc.NavbarSimple(
    brand='Frac Planning App',
    brand_href='/',
    sticky='top',
)

body = dbc.Container(
    dbc.Row(
        dbc.Col(id='page-content')
    )
)

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    navbar,
    body
])

@app.callback(Output('page-content', 'children'),
              [Input('url', 'href')],
              [State('url', 'pathname'), State('url', 'search')])
def display_page(href, pathname, search):
    print('HREF:', href)
    print('PATHAME:', pathname)
    print('SEARCH:', search)
    url = urllib.parse.urlparse(href)
    # print('RAW pathname:', url)
    print('TRIGGER(S):', [i['prop_id'] for i in dash.callback_context.triggered])
    if url.path == '/':
        return form.layout
    elif url.path == '/result':
        query = dict(urllib.parse.parse_qsl(url.query))
        return result.plot(**query)
    else:
        raise dash.exceptions.PreventUpdate

Here is the output. It doesn’t always print in the same order:

HREF: http://houmedge201:5004/
PATHAME: /
HREF: http://houmedge201:5004/
SEARCH: 
PATHAME: /
TRIGGER(S): ['url.href']
SEARCH: 
TRIGGER(S): ['url.href']

Running on Linux. Versions used:

dash                       1.7.0
dash-core-components       1.6.0
dash-html-components       1.0.2
dash-renderer              1.2.2

I’ve tried the fix mentioned in https://github.com/plotly/dash/issues/883#issuecomment-529469985 to no avail. Solving this is mission critical for my app because the duplicate callback crashes a subsequent database query.

Changing href via a html.Link makes the callback fire only once. However, users need to be able to share app URLs with query params, which right now is broken due to this bug.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 14
  • Comments: 36 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Is anyone else experiencing this issue?

@ned2 thanks for digging into this. Good to know at least some of these cases have been fixed! @luggie any chance you can post an app showing the problem you’re still seeing? We really need a reproduction case in order to get to the bottom of this. After https://github.com/plotly/dash-core-components/pull/858#discussion_r482650835 I seem to have felt we had more to do:

The boundaries of the problem have changed a little, as evidenced by this test, but it’s definitely not fixed.

but my comment may just have been based on the preceding comment by @astrowonk rather than having seen the problem myself.

It’s worth noting that whatever I was experiencing was unrelated to this issue. My old comment on the other issue/PR was inaccurate. I am not aware of this issue affecting anything I’m doing at the moment.

I’m experiencing this issue too. Digging a bit in the source code, it seems a dash-renderer problem with some components default state. Here is a quick fix to avoid this problem in Location component (https://github.com/jgoday/dash/commit/5681290f377832238d5734f6dd2409f1d7a3b097).

Need to figure out why this is happening with the location component anyway, maybe the real problem resides in dash-core-components/src/components/Loading.react.js …) 🤔

4/17/2020: However, Dash 1.11 is a great improvement over Dash 1.10 for chained callbacks with dcc.Location. I have a program with three callbacks. For the page load with Dash 1.10 the sequence was: 3, 2, 1, 1, 3, 2, 3. With Dash 1.11 the sequence is: 1, 1, 2, 3. So much better. I have a dozen other programs with similar improvements. 9/3/2020: Dash 1.16 fixes most of theses issues for my programs – major improvement.

I am experiencing the same issue. Callback with a ‘pathname’ property as input is being triggered 4 times. The result is that a chart on another page takes a few seconds to appear rather than appear instantly when I click on the button for that page. Critical issue.

Sorry, I also don’t have the code.

From: serensoner @.> Date: Sunday, 23 October 2022 at 15:37 To: plotly/dash @.> Cc: Pankratov Vitaly @.>, Mention @.> Subject: Re: [plotly/dash] [BUG] dcc.Location callback fires twice IDENTICALLY (#1049)

Hey @Samreayhttps://github.com/Samreay, @luggiehttps://github.com/luggie, or @Stayermaxhttps://github.com/Stayermax, do you have a minimal reproducible example of a Dash app that exhibits the Location callback firing twice?

Looking back through the history of the issue, I can’t actually find any code that can be used to reproduce the issue, which makes triage/diagnosis of the problem difficult. There are likely other possible causes of duplicate callbacks firing based on custom code/env setup, which would need to be eliminated from possibility.

I had a a go at creating a minimal reproducible example from the original post (which itself was not reproducible), but don’t see the behaviour. Do you in your setup? or does the example need to be changed?

from dash import Dash, html, dcc, Input, State, Output

app = Dash(name)

app.layout = html.Div([html.Div(id=“page-content”), dcc.Location(id=“url”)])

@app.callback(

Output("page-content", "children"),

Input("url", "href"),

State("url", "pathname"),

State("url", "search"),

)

def display_page(href, pathname, search):

print("HREF:", href)

print("PATHAME:", pathname)

print("SEARCH:", search)

if pathname == "/":

    return html.Div(f"HOME - Search: {search}")

return html.Div(f"{pathname} - Search: {search}")

if name == “main”:

app.run_server(debug=True)

It’s been a while since I worked on dash, but I created a minimal repro, but unfortunately only in the older versions:

requirements.txt dash==1.9.0 dash-renderer==1.7.0 Flask==2.0.0 Jinja2==3.0.3 markupsafe==2.1.1 werkzeug==2.0.0 itsdangerous==0.24

`main.py

`import dash_core_components as dcc import dash_html_components as html from dash.dependencies import Input, Output import dash

app = dash.Dash()

app.layout = html.Div([ dcc.Location(id=‘url’, refresh=False), html.Div(id=‘content’), ])

@app.callback(Output(‘content’, ‘children’), [Input(‘url’, ‘pathname’)]) def display_page(pathname): print(f’you are now at: {pathname}') return pathname

app.run_server(host=‘0.0.0.0’, debug=True) `

— Reply to this email directly, view it on GitHubhttps://github.com/plotly/dash/issues/1049#issuecomment-1288103348, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJFOCUG3AZ4CUNEQAXUNXBDWEUWQ7ANCNFSM4J3PPKIQ. You are receiving this because you were mentioned.Message ID: @.***>

Hey @Samreay, @luggie, or @Stayermax, do you have a minimal reproducible example of a Dash app that exhibits the Location callback firing twice?

Looking back through the history of the issue, I can’t actually find any code that can be used to reproduce the issue, which makes triage/diagnosis of the problem difficult. There are likely other possible causes of duplicate callbacks firing based on custom code/env setup, which would need to be eliminated from possibility.

I had a a go at creating a minimal reproducible example from the original post (which itself was not reproducible), but don’t see the behaviour. Do you in your setup? or does the example need to be changed?

from dash import Dash, html, dcc, Input, State, Output

app = Dash(__name__)

app.layout = html.Div([html.Div(id="page-content"), dcc.Location(id="url")])


@app.callback(
    Output("page-content", "children"),
    Input("url", "href"),
    State("url", "pathname"),
    State("url", "search"),
)
def display_page(href, pathname, search):
    print("HREF:", href)
    print("PATHAME:", pathname)
    print("SEARCH:", search)
    if pathname == "/":
        return html.Div(f"HOME - Search: {search}")
    return html.Div(f"{pathname} - Search: {search}")


if __name__ == "__main__":
    app.run_server(debug=True)

It’s been a while since I worked on dash, but I created a minimal repro, but unfortunately only in the older versions:

dash==1.9.0
dash-renderer==1.7.0
Flask==2.0.0
Jinja2==3.0.3
markupsafe==2.1.1
werkzeug==2.0.0
itsdangerous==0.24
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash

app = dash.Dash()

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    html.Div(id='content'),
])

@app.callback(Output('content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    print(f'you are now at: {pathname}')
    return pathname

app.run_server(host='0.0.0.0', debug=True)

Hey @Samreay, @luggie, or @Stayermax, do you have a minimal reproducible example of a Dash app that exhibits the Location callback firing twice?

Looking back through the history of the issue, I can’t actually find any code that can be used to reproduce the issue, which makes triage/diagnosis of the problem difficult. There are likely other possible causes of duplicate callbacks firing based on custom code/env setup, which would need to be eliminated from possibility.

I had a a go at creating a minimal reproducible example from the original post (which itself was not reproducible), but don’t see the behaviour. Do you in your setup? or does the example need to be changed?

from dash import Dash, html, dcc, Input, State, Output

app = Dash(__name__)

app.layout = html.Div([html.Div(id="page-content"), dcc.Location(id="url")])


@app.callback(
    Output("page-content", "children"),
    Input("url", "href"),
    State("url", "pathname"),
    State("url", "search"),
)
def display_page(href, pathname, search):
    print("HREF:", href)
    print("PATHAME:", pathname)
    print("SEARCH:", search)
    if pathname == "/":
        return html.Div(f"HOME - Search: {search}")
    return html.Div(f"{pathname} - Search: {search}")


if __name__ == "__main__":
    app.run_server(debug=True)

Yup, I also get this, very frustrating. Its not firing twice… its a single click on a dcc.Link is firing the change callback EIGHT times. A click on the daily dashboard, ventilation and back to daily gives the following console output:

@app.callback(Output("fluidContainer", "children"), [Input("url", "pathname")])
def display_dashboard(pathname):
    print(pathname)
    return locations.get(pathname)

Gives:

/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/ventilation
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily
/daily