Fix get_widget for a child element of a memoized component - #57
Draft
maartenbreddels wants to merge 1 commit into
Draft
Fix get_widget for a child element of a memoized component#57maartenbreddels wants to merge 1 commit into
maartenbreddels wants to merge 1 commit into
Conversation
A component that passes an element to a function component keeps a reference to that element and looks the widget up with get_widget(). When only the outer component re-executes, the inner component is skipped because its arguments compare equal by value. Its root element is then reused, so the widget stays registered under the element object of the previous render pass, while the caller holds a new one. We now map the old child elements to the new ones and substitute them in the reused root element, so both the element tree and get_widget() see the current objects. The map is passed down, because a component deeper in the tree can reuse its root element too, and it also reaches elements nested inside widget elements. Reworked from #48, which only covered the classic renderer and stopped at the first element boundary. Fixes widgetti/solara#927
maartenbreddels
marked this pull request as draft
September 3, 2026 12:12
Contributor
Author
|
Parking this as a draft for now. Context for picking it up later:
|
Contributor
Author
|
GitHub did not start the pull_request run for this branch; the full unit-test matrix ran via workflow_dispatch instead and passed, 23 jobs: https://github.com/widgetti/reacton/actions/runs/33753168419 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #48, fixes widgetti/solara#927.
Why
A component creates an element, passes it as a child into a function component, and calls
get_widget(el)from an effect. On a rerender where the creating component re-executes (new element object) but the receiving component is skipped because its arguments compare equal by value, the child context still maps the old element object, andget_widgetfails with "not found in all known widgets".Why #48 did not work
Two concrete gaps, not a design problem:
_render(..., old_to_new)signature change is not mirrored in_RenderContextFast._render, soREACTON_FAST=1breaks wholesale._visit_children_valuesdoes not descend into an element's own args, soHBox(children=[VBox(children=[arg])])leftargunmapped. New testtest_get_widget_fail_on_rerender_nested_widgetscovers it.What
#48's approach, an old-to-new element map threaded through
_render, applied to both renderers, with the substitution descending through nested elements, the map dropped once a component actually re-executes, and the fast renderer'sel is el_prevfast path disabled while a map is active. The helpers skip when nothing changed and when a component takes no element props.Tests: #48's three tests, plus the nested-widgets one. 190 passed on both renderers.
Please review with care
root_element.args/kwargs), as in fix: get_widget could fail with 'x not found in all known widgets' #48. A component that holds an element across renders inuse_memoor state and re-emits it could get substituted. No test covers that.old_to_newis identity-keyed; equal-but-distinct siblings map by traversal position, which relies onutils.equalsimplying structural alignment.REACTON_FAST=1, interleaved A/B:force_update_wide,memo_subtree_skip,list_reorder,teardownat parity;root_updateabout 5% slower, the element-prop walk on each skipped component.🤖 Generated with Claude Code