summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/small-maps-cough.md6
-rw-r--r--packages/astro/src/runtime/server/hydration.ts8
-rw-r--r--packages/integrations/react/client-v17.js21
-rw-r--r--packages/integrations/react/client.js21
4 files changed, 34 insertions, 22 deletions
diff --git a/.changeset/small-maps-cough.md b/.changeset/small-maps-cough.md
new file mode 100644
index 000000000..aadc443d2
--- /dev/null
+++ b/.changeset/small-maps-cough.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/react': patch
+---
+
+Fix: remove hydration failures on React v18 by exposing the "client" directive from Astro core.
diff --git a/packages/astro/src/runtime/server/hydration.ts b/packages/astro/src/runtime/server/hydration.ts
index e7267fe16..4d8ab48f0 100644
--- a/packages/astro/src/runtime/server/hydration.ts
+++ b/packages/astro/src/runtime/server/hydration.ts
@@ -110,15 +110,15 @@ export async function generateHydrateScript(
);
}
- let hydrationSource = ``;
-
- hydrationSource += renderer.clientEntrypoint
+ const hydrationSource = renderer.clientEntrypoint
? `const [{ ${
componentExport.value
}: Component }, { default: hydrate }] = await Promise.all([import("${await result.resolve(
componentUrl
)}"), import("${await result.resolve(renderer.clientEntrypoint)}")]);
- return (el, children) => hydrate(el)(Component, ${serializeProps(props)}, children);
+ return (el, children) => hydrate(el)(Component, ${serializeProps(
+ props
+ )}, children, ${JSON.stringify({ client: hydrate })});
`
: `await import("${await result.resolve(componentUrl)}");
return () => {};
diff --git a/packages/integrations/react/client-v17.js b/packages/integrations/react/client-v17.js
index 64284a0b0..32ba87558 100644
--- a/packages/integrations/react/client-v17.js
+++ b/packages/integrations/react/client-v17.js
@@ -1,15 +1,18 @@
import { createElement } from 'react';
-import { hydrate } from 'react-dom';
+import { render, hydrate } from 'react-dom';
import StaticHtml from './static-html.js';
-export default (element) => (Component, props, children) =>
- hydrate(
- createElement(
+export default (element) => (Component, props, children, { client }) =>
+ {
+ const componentEl = createElement(
Component,
- { ...props, suppressHydrationWarning: true },
+ props,
children != null
- ? createElement(StaticHtml, { value: children, suppressHydrationWarning: true })
+ ? createElement(StaticHtml, { value: children })
: children
- ),
- element
- );
+ );
+ if (client === 'only') {
+ return render(componentEl, element);
+ }
+ return hydrate(componentEl, element);
+ };
diff --git a/packages/integrations/react/client.js b/packages/integrations/react/client.js
index 7eba8984c..0579f4a08 100644
--- a/packages/integrations/react/client.js
+++ b/packages/integrations/react/client.js
@@ -1,15 +1,18 @@
import { createElement } from 'react';
-import { hydrateRoot } from 'react-dom/client';
+import { createRoot, hydrateRoot } from 'react-dom/client';
import StaticHtml from './static-html.js';
-export default (element) => (Component, props, children) =>
- hydrateRoot(
- element,
- createElement(
+export default (element) => (Component, props, children, { client }) =>
+ {
+ const componentEl = createElement(
Component,
- { ...props, suppressHydrationWarning: true },
+ props,
children != null
- ? createElement(StaticHtml, { value: children, suppressHydrationWarning: true })
+ ? createElement(StaticHtml, { value: children })
: children
- )
- );
+ );
+ if (client === 'only') {
+ return createRoot(element).render(componentEl);
+ }
+ return hydrateRoot(element, componentEl);
+ };