Skip to content

fix: keep ref in props on createElement/cloneElement - #28

Closed
letstri wants to merge 1 commit into
TanStack:mainfrom
letstri:fix/ref-as-prop
Closed

fix: keep ref in props on createElement/cloneElement#28
letstri wants to merge 1 commit into
TanStack:mainfrom
letstri:fix/ref-as-prop

Conversation

@letstri

@letstri letstri commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Base UI's render prop silently stopped working under redact — <Tooltip.Trigger render={<Button />} /> never opens, same for popovers and menus. No error.

It clones the element with a merged ref:

mergedProps.ref = props.ref;
return React.cloneElement(newElement, mergedProps);

React 19 keeps ref in props (only key/__self/__source are reserved), but redact
follows the React 18 rule and hoists it onto element.ref, so the cloned function
component gets no ref. The trigger element never reaches the tooltip store and the
hover effect bails before attaching its mouseenter listener.

Fix: createElement/cloneElement leave ref in props, and cloneElement skips
it only when config.ref === undefined, like React does.

Summary by CodeRabbit

  • Bug Fixes

    • Preserved ref as a regular prop when creating and cloning React elements, aligning with React 19 behavior.
    • Prevented cloning without a new ref from unintentionally replacing an existing ref.
    • Ensured cloned refs are forwarded correctly through function components to the underlying DOM element.
  • Tests

    • Added coverage for ref retention, cloning behavior, and end-to-end ref forwarding.

@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 44700401-84ce-4593-bf70-4de6bbbaa3c2

📥 Commits

Reviewing files that changed from the base of the PR and between aa8730a and 77f0020.

📒 Files selected for processing (3)
  • .changeset/ref-as-prop.md
  • packages/redact/src/react/element.ts
  • tests/element-ref-prop.test.tsx

Included review availability: Your plan provides up to 2 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The React element helpers now preserve refs as regular props. cloneElement avoids replacing an existing ref with undefined. Tests cover creation, cloning, prop merging, and DOM forwarding.

Changes

React ref prop preservation

Layer / File(s) Summary
Preserve refs in element helpers
packages/redact/src/react/element.ts, .changeset/ref-as-prop.md
createElement copies ref into props. cloneElement skips an undefined ref. The changeset documents the patch release.
Validate ref forwarding behavior
tests/element-ref-prop.test.tsx
Tests verify ref retention in created and cloned elements, preservation during cloning without a new ref, and forwarding to a rendered <span>.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 77f00

The ref-as-prop behavior is implemented and covered across the affected element creation, cloning, and DOM-forwarding paths; no actionable merge risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preserving ref in props for createElement and cloneElement.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tannerlinsley

Copy link
Copy Markdown
Member

Thanks for catching this, Valerii. The ref-as-prop fix is now merged in #29, with your co-author credit, legacy-ref coverage, and size/performance checks. Closing this in favor of the merged PR.

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.

2 participants