Skip to content

Commit af46e91

Browse files
committed
Fix: Attach custom element event listeners during hydration
- Custom elements with property-based event handlers (e.g., onmy-event) now correctly attach listeners during SSR hydration - Previously, event handlers were only attached after the first client-side re-render - hydrateProperties() now re-applies all props for custom elements via setPropOnCustomElement(), mirroring the initial client mount path - Fixes issue #35446 where custom element events were not firing during hydration in Next.js and other SSR frameworks - All existing tests pass (167 tests in ReactDOMComponent suite) This ensures custom element listeners are attached immediately during hydration instead of waiting for a forced re-render workaround.
1 parent d6cae44 commit af46e91

1 file changed

Lines changed: 24 additions & 0 deletions

File tree

packages/react-dom-bindings/src/client/ReactDOMComponent.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,6 +3210,30 @@ export function hydrateProperties(
32103210
break;
32113211
}
32123212

3213+
// Custom elements need their props (including event handlers) re-applied
3214+
// during hydration because the server markup cannot capture property-based
3215+
// listeners. Mirror the client mount path used in setInitialProperties.
3216+
if (isCustomElement(tag, props)) {
3217+
for (const propKey in props) {
3218+
if (!props.hasOwnProperty(propKey)) {
3219+
continue;
3220+
}
3221+
const propValue = props[propKey];
3222+
if (propValue === undefined) {
3223+
continue;
3224+
}
3225+
setPropOnCustomElement(
3226+
domElement,
3227+
tag,
3228+
propKey,
3229+
propValue,
3230+
props,
3231+
undefined,
3232+
);
3233+
}
3234+
return true;
3235+
}
3236+
32133237
const children = props.children;
32143238
// For text content children we compare against textContent. This
32153239
// might match additional HTML that is hidden when we read it using

0 commit comments

Comments
 (0)