-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
Environment
dash 4.0.0
Hello, I've been getting into the wonderful world of extensibility, dash.Patch() and pattern matching callbacks.
Click a button, a new input appears, ect. But I have run into an issue when using pattern matching callbacks.
When a new element is appended via dash. Patch(), the initial callbacks run against every element of that type.
I have created a minimum test app to show the issue.
When clicking the "Add Slider" button, I would expect to see the print_callback_value function run once per click. Instead I see it run multiple times, once per element.
This can be seen in the console as well as the debug dash callbacks view.
10 slider creations cause 56 init callbacks.
This causes performance issues with multiple sliders. It creates flickering as the elements are setup, and may have errors related to unexpected reinit callbacks, they have no ctx.triggered.
I have also created this PR as a suggested fix. #3682
from dash import Dash, dcc, html, Input, Output, callback, State, ctx, Patch, MATCH, no_update, clientside_callback, ALL
from dash.exceptions import PreventUpdate
app = Dash(__name__)
app.layout = html.Div(
children=[
dcc.Button(id='add_slider_btn', children='Add Slider'),
html.Div(id='slider_container', children=[])
])
@callback(
Output({'type': 'slider','aio_id': ALL}, 'value'),
Input({'type': 'slider','aio_id': ALL}, 'value'),
prevent_initial_call=False
)
def print_callback_value(val):
print(f'{ctx.triggered_id=} = {val}')
raise PreventUpdate
@callback(Output("slider_container", "children"),
Input("add_slider_btn", "n_clicks"),
prevent_initial_call=True,
)
def add_new_slider(n_clicks):
sliders_container_patch = Patch()
sliders_container_patch.append(
dcc.Slider(id={
'type': 'slider',
'aio_id': str(n_clicks)
},
step=0.1,
persistence=True, persistence_type='local'
)
)
return sliders_container_patch
if __name__ == '__main__':
app.run(debug=True)