Skip to content

Commit c43f2c4

Browse files
fix(renderer): clear child paths when callback returns None
1 parent fdedbbf commit c43f2c4

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

‎dash/dash-renderer/src/observers/executedCallbacks.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ const observer: IStoreObserverDefinition<IStoreState> = {
321321
childrenPropPath,
322322
appliedProps
323323
);
324-
if (!children) {
324+
if (children === undefined) {
325325
return;
326326
}
327327

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import time
2+
3+
from dash import Dash, Input, Output, dcc, html
4+
from dash.testing.wait import until
5+
6+
7+
def test_callback_returning_none_removes_child_paths_and_can_remount(dash_duo):
8+
view_calls = []
9+
10+
app = Dash(__name__, suppress_callback_exceptions=True)
11+
app.layout = html.Div(
12+
[
13+
html.Button("Toggle", id="toggle"),
14+
dcc.Interval(id="tick", interval=200),
15+
html.Div(id="container"),
16+
]
17+
)
18+
19+
@app.callback(
20+
Output("container", "children"),
21+
Input("toggle", "n_clicks"),
22+
prevent_initial_call=True,
23+
)
24+
def toggle_view(n_clicks):
25+
if n_clicks % 2:
26+
return html.Div(html.Span(id="view-child"), id="view")
27+
return None
28+
29+
@app.callback(Output("view-child", "children"), Input("tick", "n_intervals"))
30+
def update_view(n_intervals):
31+
view_calls.append(n_intervals)
32+
return f"tick {n_intervals}"
33+
34+
dash_duo.start_server(app)
35+
36+
dash_duo.find_element("#toggle").click()
37+
dash_duo.wait_for_element("#view-child")
38+
until(lambda: "view-child" in dash_duo.redux_state_paths["strs"], timeout=3)
39+
until(lambda: view_calls, timeout=3)
40+
41+
dash_duo.find_element("#toggle").click()
42+
dash_duo.wait_for_no_elements("#view-child")
43+
until(lambda: "view-child" not in dash_duo.redux_state_paths["strs"], timeout=3)
44+
calls_after_unmount = len(view_calls)
45+
time.sleep(0.5)
46+
assert len(view_calls) == calls_after_unmount
47+
48+
dash_duo.find_element("#toggle").click()
49+
dash_duo.wait_for_element("#view-child")
50+
until(lambda: "view-child" in dash_duo.redux_state_paths["strs"], timeout=3)

0 commit comments

Comments
 (0)