react-elegant-ui
Version:
Elegant UI components, made by BEM best practices for react
83 lines • 2.88 kB
JavaScript
var __read = this && this.__read || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o),
r,
ar = [],
e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
} catch (error) {
e = {
error: error
};
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
};
import React, { createContext, useContext, useEffect, useRef, useState } from 'react';
import { canUseDOM } from '../lib/canUseDOM';
import { SimpleEventChannel } from '../lib/SimpleEventChannel';
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export var SSRContext = /*#__PURE__*/createContext(true);
export var SSREventManagerContext = /*#__PURE__*/createContext(null);
/**
* Component which provide SSR context and force re-render on client side
*
* This behavior is required to first render on client will match with SSR structure
* It may be useful for SEO purposes or graceful degradation to no-js level
*
* This component must be used on top level of application, and preferred only once
*/
export var SSRProvider = function (_a) {
var children = _a.children;
var _b = __read(useState(false), 2),
isRendered = _b[0],
setIsRendered = _b[1];
var eventManagerRef = useRef(null);
// Create event manager only on client side
if (canUseDOM() && eventManagerRef.current === null) {
eventManagerRef.current = new SimpleEventChannel();
}
// Start client side render after render all children nodes
useIsomorphicLayoutEffect(function () {
setIsRendered(true);
if (eventManagerRef.current !== null) {
eventManagerRef.current.send(true);
}
}, []);
return /*#__PURE__*/React.createElement(SSRContext.Provider, {
value: isRendered
}, /*#__PURE__*/React.createElement(SSREventManagerContext.Provider, {
value: eventManagerRef.current
}, children));
};
/**
* Hook to render content depends on render context (SSR/CSR)
*
* It will always return `false` on SSR and while first render on CSR,
* but will `true` when all child nodes of `SSRProvider` will rendered on client side
*
* This hook should be used with `SSRProvider` parent, otherwise it will return `true` always
*/
export var useIsReadyToCSR = function () {
var isReadyToCSR = useContext(SSRContext);
var _a = __read(useState(isReadyToCSR), 2),
isReady = _a[0],
setIsReady = _a[1];
// Observe context, to update state for memoized components
var eventManager = useContext(SSREventManagerContext);
useEffect(function () {
if (eventManager === null) return;
eventManager.subscribe(setIsReady);
return function () {
eventManager.unsubscribe(setIsReady);
};
}, [eventManager]);
return isReady || isReadyToCSR;
};