Skip to content

Conversation

@sleitor
Copy link

@sleitor sleitor commented Dec 13, 2025

Summary

Use Children.toArray in SlotClone to properly unwrap React lazy components that have non-PromiseLike payloads (common in RSC context).

Problem: The existing isLazyComponent check requires isPromiseLike(element._payload), but in RSC context the _payload may have a different structure, causing lazy references to slip through and break cloneElement. This results in components not rendering in production builds.

Solution: Use Children.toArray which internally resolves lazy children regardless of payload structure, making it a robust solution for RSC compatibility.

Fixes #3776

Changes

  • Replace isLazyComponent + isValidElement(children) approach with Children.toArray in createSlotClone
  • Early return for multiple children error (maintains original behavior)
  • Clean separation of concerns with clear comments

Test plan

  • Existing unit tests pass (10 passed, 2 skipped)
  • Tested in real Next.js 16 application with Turbopack production build
  • Verified nested Dialog trigger renders correctly in production

Related issues

Use `Children.toArray` in `SlotClone` to properly unwrap React lazy components. The existing `isLazyComponent` check requires `isPromiseLike(element._payload)`, but in RSC context the `_payload` may have a different structure, causing lazy references to slip through and break `cloneElement`. `Children.toArray` internally resolves lazy children regardless of payload structure, making it a robust solution for RSC compatibility. Related issues: - facebook/react#32392 - vercel/next.js#82527 - radix-ui#3776
@changeset-bot
Copy link

changeset-bot bot commented Dec 13, 2025

🦋 Changeset detected

Latest commit: e2ac304

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 44 packages
Name Type
@radix-ui/react-slot Patch
@radix-ui/react-alert-dialog Patch
@radix-ui/react-collection Patch
@radix-ui/react-dialog Patch
@radix-ui/react-menu Patch
@radix-ui/react-popover Patch
@radix-ui/react-primitive Patch
radix-ui Patch
@radix-ui/react-select Patch
@radix-ui/react-tooltip Patch
@radix-ui/react-accordion Patch
@radix-ui/react-menubar Patch
@radix-ui/react-navigation-menu Patch
@radix-ui/react-one-time-password-field Patch
@radix-ui/react-roving-focus Patch
@radix-ui/react-slider Patch
@radix-ui/react-toast Patch
@radix-ui/react-context-menu Patch
@radix-ui/react-dropdown-menu Patch
@radix-ui/react-announce Patch
@radix-ui/react-arrow Patch
@radix-ui/react-aspect-ratio Patch
@radix-ui/react-avatar Patch
@radix-ui/react-checkbox Patch
@radix-ui/react-collapsible Patch
@radix-ui/react-dismissable-layer Patch
@radix-ui/react-focus-scope Patch
@radix-ui/react-form Patch
@radix-ui/react-hover-card Patch
@radix-ui/react-label Patch
@radix-ui/react-password-toggle-field Patch
@radix-ui/react-popper Patch
@radix-ui/react-portal Patch
@radix-ui/react-progress Patch
@radix-ui/react-radio-group Patch
@radix-ui/react-scroll-area Patch
@radix-ui/react-separator Patch
@radix-ui/react-switch Patch
@radix-ui/react-tabs Patch
@radix-ui/react-toggle-group Patch
@radix-ui/react-toggle Patch
@radix-ui/react-toolbar Patch
@radix-ui/react-visually-hidden Patch
@radix-ui/react-accessible-icon Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

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

Labels

None yet

1 participant