Skip to content

fix(renderer): clear paths for null children - #4052

Open
0d00ciallo0721 wants to merge 3 commits into
plotly:devfrom
0d00ciallo0721:agent-tasks/4033
Open

0d00ciallo0721 wants to merge 3 commits into
plotly:devfrom
0d00ciallo0721:agent-tasks/4033

Conversation

@0d00ciallo0721

Copy link
Copy Markdown

Fixes #4033.

Dash serializes a callback returning None for children as an explicit null value. The renderer treated all falsy child values as if the callback had omitted the property, so it skipped path recomputation. Removed descendants stayed in the Redux path table, allowing their callbacks to keep firing and preventing a clean remount. The renderer now skips recomputation only when the output property is absent (undefined).

Contributor Checklist

  • Scope: recompute paths for explicit children values, including null.
    • Add a browser integration regression for removing and remounting callback-generated children.
  • Run the relevant tests locally.
  • Add regression coverage for the bug.

Validation

  • python -m pytest tests/integration/callbacks/test_children_none.py --headless -xvs — passed; the same test failed on the unmodified base when the removed child remained in the path table.
  • python -m pytest tests/integration/callbacks/test_layout_paths_with_callbacks.py tests/integration/callbacks/test_wildcards.py -k 'cblp001 or cbwc003 or cbwc011 or cbwc014' --headless -xvs — 4 passed.
  • npm test in dash/dash-renderer — 123 passed.
  • Renderer build and npm run private::lint.renderer — successful. ESLint reported three warnings in untouched files.
  • Black, Flake8, and git diff --check — passed.

@0d00ciallo0721
0d00ciallo0721 marked this pull request as ready for review October 6, 2026 08:40

@T4rk1n T4rk1n left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix is right, and nothing blocks merge. null (and "" / 0) is an explicit value that replaces the subtree, so the old paths have to be cleared. Only undefined means the prop wasn't returned. The test reproduces #4033 and checks both halves of it (callbacks stop after unmount, remount works).

The [] branch just above (if (!frontObj) return;, around line 291) has the same falsy check. A callback that sets options=None on a Checklist whose options[].label holds components with callbacks would leave those labels registered. Could you switch it to === undefined too? I'm fine with that being a follow-up.

appliedProps
);
if (!children) {
if (children === undefined) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also fixes children="" and children=0, which had the same stale-paths bug. Can you add a renderer test or a second case in the integration test so nobody puts back a !children check later?

from dash.testing.wait import until


def test_callback_returning_none_removes_child_paths_and_can_remount(dash_duo):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you follow the test_cbXXnnn_ naming used in the rest of this folder? Or move it into test_layout_paths_with_callbacks.py as the next cblp test, so it doesn't sit alone in a new file.


dash_duo.find_element("#toggle").click()
dash_duo.wait_for_element("#view-child")
until(lambda: "view-child" in dash_duo.redux_state_paths["strs"], timeout=3)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the remount, can you also wait for the tick text in #view-child (dash_duo.wait_for_contains_text)? Having the path back doesn't show that update_view is wired to the new child again, and that's the visible symptom in the issue.

@sonarqubecloud

Copy link
Copy Markdown

@0d00ciallo0721

Copy link
Copy Markdown
Author

Hi, I pushed the requested regression coverage for children values None, empty string, and zero in commit b099837; the integration cases pass locally. GitHub marked the Dash Testing and Performance Benchmarks runs as action_required without starting jobs. Could someone with admin access approve these workflow runs so CI can execute? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Setting children to None leaves removed components registered: their callbacks keep firing and the subtree can never be mounted again

2 participants