Fix: React - Use "createRoot" instead of "hydrateRoot" for client:only
(#3337)
* feat: pass "client" directive to clientEntrypoints * refactor: remove hydration warning suppression react 17 * feat: remove hydration warning suppression react 18 * chore: changeset * fix: change metadata to options bag
This commit is contained in:
parent
13e697fb80
commit
678c2b7523
4 changed files with 34 additions and 22 deletions
6
.changeset/small-maps-cough.md
Normal file
6
.changeset/small-maps-cough.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'astro': patch
|
||||
'@astrojs/react': patch
|
||||
---
|
||||
|
||||
Fix: remove hydration failures on React v18 by exposing the "client" directive from Astro core.
|
|
@ -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 () => {};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue