Skip to content

fix: make Markdown a MemoizationLeaf so Var children stay inlined#6532

Merged
masenf merged 2 commits into
reflex-dev:mainfrom
FarhanAliRaza:markdown-component-memo-fix
May 19, 2026
Merged

fix: make Markdown a MemoizationLeaf so Var children stay inlined#6532
masenf merged 2 commits into
reflex-dev:mainfrom
FarhanAliRaza:markdown-component-memo-fix

Conversation

@FarhanAliRaza
Copy link
Copy Markdown
Contributor

@FarhanAliRaza FarhanAliRaza commented May 19, 2026

react-markdown asserts its children prop is a string. Without the snapshot boundary, the auto-memoize plugin hoists a Var child into its own Bare_comp_ element, which renders as [object Object] and crashes the subtree.

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally prior to submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

closes #6531

fixes ENG-9539

react-markdown asserts its children prop is a string. Without the snapshot
boundary, the auto-memoize plugin hoists a Var child into its own
Bare_comp_<hash> element, which renders as [object Object] and crashes
the subtree.
@FarhanAliRaza FarhanAliRaza requested a review from a team as a code owner May 19, 2026 18:53
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 19, 2026

Greptile Summary

This PR fixes a runtime crash where rx.markdown(State.var) would render [object Object] instead of the Var's string value. The root cause was the auto-memoize plugin hoisting the Var child into a Bare_comp_<hash> React element, while react-markdown requires its children prop to be a string.

  • Core fix: Markdown now inherits from MemoizationLeaf instead of Component, which sets _memoization_mode = MemoizationMode(recursive=False) and keeps any Var child inlined in the snapshot body rather than being hoisted out as a separate React element.
  • Tests: A unit test that runs the full compiler pipeline and asserts no Bare_comp_ is emitted, plus a Playwright integration test that verifies the rendered text and that [object Object] is never visible.

Confidence Score: 5/5

The change is minimal and correctly targeted: swapping the base class for Markdown to MemoizationLeaf prevents the auto-memoize plugin from hoisting Var children out as separate React elements, which was the source of the crash.

The fix is a single-line base-class change backed by two levels of tests (a full-compiler unit test and a Playwright integration test). The two review comments flag test-quality concerns — a potential state-name collision in repeated test runs and reliance on internal compiler APIs — neither of which affects production behavior.

The test helper _compile_page_output in tests/units/components/markdown/test_markdown.py accesses several internal compiler APIs that could drift; it warrants a second look if compiler internals are refactored.

Important Files Changed

Filename Overview
packages/reflex-components-markdown/src/reflex_components_markdown/markdown.py Single-line base-class change from Component to MemoizationLeaf; docstring updated to explain the snapshot-boundary rationale. No logic changes.
tests/units/components/markdown/test_markdown.py Adds _compile_page_output helper and test_markdown_var_child_inlined_not_wrapped that run the full compiler pipeline; accesses several internal APIs that could shift independently of this fix.
tests/integration/tests_playwright/test_memoize_edge_cases.py Adds state variable + event handler for markdown source, a Var-driven rx.markdown component, and a Playwright test that verifies initial render and state-update behavior.
pyi_hashes.json Hash for markdown.pyi updated to reflect the base-class change; mechanical bookkeeping.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["rx.markdown(State.var)"] --> B{Markdown base class}
    B -->|Before: Component| C["Auto-memoize plugin scans children"]
    C --> D["Var child hoisted into Bare_comp_hash React element"]
    D --> E["ReactMarkdown receives JSX element as children"]
    E --> F["Renders as '[object Object]' / crash"]
    B -->|After: MemoizationLeaf| G["_memoization_mode = recursive=False"]
    G --> H["Var child stays inlined in snapshot body"]
    H --> I["ReactMarkdown receives string interpolation as children"]
    I --> J["Renders correctly"]
Loading

Reviews (1): Last reviewed commit: "fix: make Markdown a MemoizationLeaf so ..." | Re-trigger Greptile

Comment thread tests/units/components/markdown/test_markdown.py Outdated
Comment thread tests/units/components/markdown/test_markdown.py
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 19, 2026

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing FarhanAliRaza:markdown-component-memo-fix (5aa7159) with main (6112083)

Open in CodSpeed

Defining the State subclass inside the test body re-registers it on every
collection, which leaks under pytest-repeat and duplicate runs. Module
scope gives it a stable registry key.
@masenf masenf merged commit 70bd785 into reflex-dev:main May 19, 2026
70 checks passed
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.

rx.markdown not working with State var

2 participants