@base-ui/react
Version:
Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.
54 lines (52 loc) • 2.19 kB
JavaScript
'use client';
import * as React from 'react';
import { useIsHydrating } from "../utils/useIsHydrating.mjs";
import { useCSPContext } from "./csp-context/CSPContext.mjs";
/**
* Renders an inline script that runs before React hydrates, used by components that need
* to position server-rendered content ahead of hydration (e.g. `Tabs.Indicator`,
* `Slider.Thumb`).
*
* The `script` source is imported by the caller through the package's `#prehydration/*`
* subpath import, whose `browser` condition resolves to a stub module exporting an empty
* string — so the script body is excluded from client bundles. It only ever executes from
* server-rendered HTML.
*
* Render this only when the script should be emitted (i.e. gate `renderBeforeHydration`
* and any structural conditions at the call site). The element is still rendered (with
* empty content) on the client during the hydration pass so the React tree matches the
* server markup; `suppressHydrationWarning` bridges the content difference and React keeps
* the already-executed server script. Once `isHydrating` flips to `false` the element
* unmounts.
*
* The component must stay in client bundles: returning `null` on the client (e.g. by
* stubbing the whole component) would drop an element the server emitted and trigger a
* recoverable hydration error (React #418) in consumers' apps. Only the script body is
* excluded from client bundles, via the `#prehydration/*` `browser` condition.
*
* When adding a new consumer, register a matching `#prehydration/*` entry (with `browser`
* and `default` conditions) in `packages/react/package.json` `imports`; the `browser`
* condition reuses the shared `internals/prehydrationScript.stub.ts`.
*/
import { jsx as _jsx } from "react/jsx-runtime";
export function PrehydrationScript(props) {
const {
script
} = props;
const {
nonce
} = useCSPContext();
const isHydrating = useIsHydrating();
if (!isHydrating) {
return null;
}
return /*#__PURE__*/_jsx("script", {
nonce: nonce
// eslint-disable-next-line react/no-danger
,
dangerouslySetInnerHTML: {
__html: script
},
suppressHydrationWarning: true
});
}