-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
Describe the Bug
In Astro 5.16.9, React components with mouse event handlers (e.g., onMouseDown, onMouseMove, onMouseUp) stop working when nested inside HTML elements in MDX files. This is a regression introduced by PR #15150.
Steps to Reproduce
In an MDX file:
<div className="wrapper">
<InteractiveComponent
onMouseDown={(e) => console.log('mousedown')}
onMouseMove={(e) => console.log('mousemove')}
client:load
/>
</div>InteractiveComponent.tsx:
export const InteractiveComponent = ({ onMouseDown, onMouseMove }) => {
return (
<div
onMouseDown={onMouseDown}
onMouseMove={onMouseMove}
>
Drag me
</div>
);
};Expected Behavior
- ✅ 5.16.8 and earlier: Mouse events work correctly
- ✅ 5.16.6: Mouse events work correctly
Actual Behavior
- ❌ 5.16.9: Mouse events do not fire, component renders static HTML without hydration
Root Cause Analysis
PR #15150 modified the array rendering logic in packages/astro/src/runtime/server/jsx.ts:
Before (5.16.8):
case Array.isArray(vnode):
return markHTMLString(
(await Promise.all(vnode.map((v: any) => renderJSX(result, v)))).join(''),
);After (5.16.9):
case Array.isArray(vnode): {
const renderedItems = await Promise.all(vnode.map((v: any) => renderJSX(result, v)));
let instructions: RenderInstruction[] | null = null;
let content = '';
for (const item of renderedItems) {
if (item instanceof SlotString) {
content += item;
instructions = mergeSlotInstructions(instructions, item);
} else {
content += item; // ← Components treated as plain strings
}
}
// ...
}The problem: When React components are nested in HTML elements within MDX, the children array processing now treats non-SlotString items as plain HTML strings, stripping the hydration mechanism (no <astro-island> tags are output).
Workaround
Move the className to the component props instead of wrapping in a div:
<InteractiveComponent
className="wrapper"
onMouseDown={(e) => console.log('mousedown')}
client:load
/>This avoids the array processing logic that causes the issue.
Impact
- Breaks all React components with event handlers when nested in MDX
- Affects third-party components that cannot be easily modified
- Workaround is not always feasible (semantic HTML structure, layout requirements)
Environment
- Astro Version: 5.16.9
- Works in: 5.16.8, 5.16.6
- Related PR: Fix hydration for framework components in MDX slots #15150 (fix for MDX slot hydration)
Suggested Fix
The array rendering logic should preserve hydration for all rendered components, not just SlotString instances. The fix for MDX slots inadvertently broke non-slot scenarios.