UNPKG

@shopify/react-html

Version:

A component to render your React app with no static HTML

79 lines (72 loc) 2.56 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var reactHydrate = require('@shopify/react-hydrate'); var hooks = require('../hooks.js'); var utilities = require('../utilities.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); function HtmlUpdater() { const queuedUpdate = React__default["default"].useRef(null); hooks.useClientDomEffect(manager => { return manager.subscribe(state => { if (queuedUpdate.current) { cancelAnimationFrame(queuedUpdate.current); } queuedUpdate.current = requestAnimationFrame(() => { updateOnClient(state); }); }); }); return /*#__PURE__*/React__default["default"].createElement(reactHydrate.HydrationTracker, null); } function updateOnClient(state) { const { title, metas, links, inlineStyles } = state; let titleElement = document.querySelector('title'); if (title == null) { if (titleElement) { titleElement.remove(); } } else { if (titleElement == null) { titleElement = document.createElement('title'); document.head.appendChild(titleElement); } titleElement.setAttribute(utilities.MANAGED_ATTRIBUTE, 'true'); titleElement.textContent = title; } const fragment = document.createDocumentFragment(); updateElement('meta', utilities.removeDuplicate(metas), fragment); updateElement('link', links, fragment); updateElement('style', inlineStyles, fragment); document.head.appendChild(fragment); } function updateElement(selector, items, fragment) { const oldElements = Array.from(document.head.querySelectorAll(`${selector}[${utilities.MANAGED_ATTRIBUTE}]`)); for (const item of items) { const element = document.createElement(selector); element.setAttribute(utilities.MANAGED_ATTRIBUTE, 'true'); for (const [attribute, value] of Object.entries(item)) { if (attribute === 'children') { element.textContent = value; } else { element.setAttribute(attribute, value); } } const matchingOldElementIndex = oldElements.findIndex(oldElement => oldElement.isEqualNode(element)); if (matchingOldElementIndex >= 0) { oldElements.splice(matchingOldElementIndex, 1); } else { fragment.appendChild(element); } } for (const oldElement of oldElements) { oldElement.remove(); } } exports.HtmlUpdater = HtmlUpdater;