UNPKG

react-elegant-ui

Version:

Elegant UI components, made by BEM best practices for react

83 lines 2.88 kB
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; };