60 lines
2.4 KiB
JavaScript
60 lines
2.4 KiB
JavaScript
|
import * as React from 'react';
|
||
|
import { canUseDOM } from './canUseDOM';
|
||
|
/**
|
||
|
* Default context value to use in case there is no SSRProvider. This is fine for client-only apps.
|
||
|
*
|
||
|
* @internal
|
||
|
*/ export const defaultSSRContextValue = {
|
||
|
current: 0
|
||
|
};
|
||
|
export const SSRContext = /*#__PURE__*/ React.createContext(undefined);
|
||
|
/**
|
||
|
* @internal
|
||
|
*/ export function useSSRContext() {
|
||
|
var _React_useContext;
|
||
|
return (_React_useContext = React.useContext(SSRContext)) !== null && _React_useContext !== void 0 ? _React_useContext : defaultSSRContextValue;
|
||
|
}
|
||
|
/**
|
||
|
* When using SSR with Fluent UI, applications must be wrapped in an SSRProvider. This ensures that auto generated ids
|
||
|
* are consistent between the client and server.
|
||
|
*
|
||
|
* @public
|
||
|
*/ export const SSRProvider = (props)=>{
|
||
|
const [value] = React.useState(()=>({
|
||
|
current: 0
|
||
|
}));
|
||
|
return /*#__PURE__*/ React.createElement(SSRContext.Provider, {
|
||
|
value: value
|
||
|
}, props.children);
|
||
|
};
|
||
|
/**
|
||
|
* Returns whether the component is currently being server side rendered or hydrated on the client. Can be used to delay
|
||
|
* browser-specific rendering until after hydration. May cause re-renders on a client when is used within SSRProvider.
|
||
|
*/ export function useIsSSR() {
|
||
|
const isInSSRContext = useSSRContext() !== defaultSSRContextValue;
|
||
|
const [isSSR, setIsSSR] = React.useState(isInSSRContext);
|
||
|
// If we are rendering in a non-DOM environment, and there's no SSRProvider, provide a warning to hint to the
|
||
|
// developer to add one.
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
if (!isInSSRContext && !canUseDOM()) {
|
||
|
// eslint-disable-next-line no-console
|
||
|
console.error(`@fluentui/react-components [${useIsSSR.name}]:
|
||
|
When server rendering, you must wrap your application in an <SSRProvider> to ensure consistent ids are generated between the client and server.
|
||
|
|
||
|
|
||
|
Check documentation at https://aka.ms/fluentui-ssr.`);
|
||
|
}
|
||
|
}
|
||
|
// If on the client, and the component was initially server rendered, then schedule a layout effect to update the
|
||
|
// component after hydration.
|
||
|
if (canUseDOM() && isInSSRContext) {
|
||
|
// This if statement technically breaks the rules of hooks, but is safe because the condition never changes after
|
||
|
// mounting.
|
||
|
// eslint-disable-next-line
|
||
|
React.useLayoutEffect(()=>{
|
||
|
setIsSSR(false);
|
||
|
}, []);
|
||
|
}
|
||
|
return isSSR;
|
||
|
}
|