Files
reactShop/src/utils/LazySanitizedHtml.js

53 lines
2.1 KiB
JavaScript

import React, { lazy, Suspense } from 'react';
// Load html-react-parser and sanitize-html in a single async chunk.
// Neither library ships in the main bundle — they are only fetched when a
// component that uses this wrapper actually renders.
const SanitizedHtmlContent = lazy(() =>
Promise.all([
import(/* webpackChunkName: "html-parser" */ 'html-react-parser'),
import(/* webpackChunkName: "html-parser" */ 'sanitize-html'),
]).then(([{ default: parse }, { default: sanitizeHtml }]) => ({
default: function SanitizedHtmlContent({ html, sanitizeOptions, parseOptions }) {
try {
// sanitizeOptions can be a plain object or a factory (fn) that receives
// the sanitizeHtml module so callers can reference sanitizeHtml.defaults.
const resolvedSanitizeOptions =
typeof sanitizeOptions === 'function'
? sanitizeOptions(sanitizeHtml)
: sanitizeOptions;
const sanitized = sanitizeHtml(html, resolvedSanitizeOptions);
return parse(sanitized, parseOptions);
} catch (error) {
console.warn('LazySanitizedHtml: failed to parse HTML', error);
return <span>{html}</span>;
}
},
}))
);
/**
* Renders sanitized and parsed HTML without including sanitize-html or
* html-react-parser in the initial JavaScript bundle.
*
* @param {string} html Raw HTML string to sanitize and render
* @param {object|function} sanitizeOptions sanitize-html options object, or a
* factory (sanitizeHtml) => options so
* callers can use sanitizeHtml.defaults
* @param {object} parseOptions html-react-parser options (e.g. replace)
* @param {React.ReactNode} fallback Shown while the libraries are loading
*/
export default function LazySanitizedHtml({ html, sanitizeOptions, parseOptions, fallback = null }) {
if (!html) return null;
return (
<Suspense fallback={fallback}>
<SanitizedHtmlContent
html={html}
sanitizeOptions={sanitizeOptions}
parseOptions={parseOptions}
/>
</Suspense>
);
}