Pattern Matching Callback Renders All Components When Adding New One
Describe your context Please provide us your environment, so we can easily reproduce the issue.
dash 2.13.0
dash-core-components 2.0.0
dash-enterprise-libraries 1.3.0
dash-html-components 2.0.0
dash_mantine_components 0.14.3
dash-table 5.0.0
Describe the bug
I'm using a sample app from the documentation that uses a pattern matching callback (MATCH). I added a dcc.Loading component, and the problem is that when I add a new pair of components, all the old components get refreshed too.
Expected behavior
When I add a new component, only the new component should be rendered.
Screenshots
Code
from dash import Dash, dcc, html, Input, Output, State, MATCH, Patch, callback
app = Dash(__name__)
app.layout = html.Div([
html.Button("Add Filter", id="dynamic-add-filter-btn", n_clicks=0),
html.Div(id='dynamic-dropdown-container-div', children=[]),
])
@callback(
Output('dynamic-dropdown-container-div', 'children'),
Input('dynamic-add-filter-btn', 'n_clicks')
)
def display_dropdowns(n_clicks):
patched_children = Patch()
new_element = html.Div([
dcc.Dropdown(
['NYC', 'MTL', 'LA', 'TOKYO'],
id={
'type': 'city-dynamic-dropdown',
'index': n_clicks
}
),
dcc.Loading(
# id={"type": "file-loading", "index": idx},
type="default",
children=html.Div(
id={
'type': 'city-dynamic-output',
'index': n_clicks
}
))
])
patched_children.append(new_element)
return patched_children
@callback(
Output({'type': 'city-dynamic-output', 'index': MATCH}, 'children'),
Input({'type': 'city-dynamic-dropdown', 'index': MATCH}, 'value'),
State({'type': 'city-dynamic-dropdown', 'index': MATCH}, 'id'),
)
def display_output(value, id):
import time, random
sleep_time = random.randint(1, 5)
time.sleep(sleep_time)
print(html.Div(f"Dropdown {id['index']} = {value}"))
return html.Div(f"Dropdown {id['index']} = {value}")
if __name__ == '__main__':
app.run(debug=True)
@andre996 just add prevent_initial_call=True:
To my knowledge this (prevent_initial_call=True) only works when the app first starts. When dynamically adding components to an app, the callback with the pattern matching input will be triggered every time a new component is rendered.
And if the above argument is supposed to prevent this from happening, I can assure you it isn't.