react-oc
Version:
A React component that allows OpenComponents to operate within a react application.
89 lines (74 loc) • 3.08 kB
JavaScript
import React from 'react';
import { OCContext } from "./OCContext";
import { dangerousHtml } from "./lib/dangerousHtml";
export class Prefetched extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
render() {
const { id, className, prefetchKey, captureAs } = this.props;
if (!prefetchKey) {
throw new Error(`Mandatory prop 'prefetchKey' was not provided.`);
}
return <OCContext.Consumer>{
(context) => {
if (!context) {
throw new Error('OpenComponent.Prefetched must be nested within a <ComponentContext />');
}
this.oc = context.oc;
this.saveElements = context.saveElements;
this.capturedElements = this.props.captureAs && context.getElements(this.props.captureAs);
this.html = this.capturedElements ? '' : context.getHtml(prefetchKey);
let suppressHydrationWarning = false;
if (this.html === undefined) {
this.html = this.props.fallback || '';
suppressHydrationWarning = true;
}
const html = dangerousHtml(this.html);
return <div ref={this.ref}
id={id} className={className}
dangerouslySetInnerHTML={html}
suppressHydrationWarning={suppressHydrationWarning} />;
}
}</OCContext.Consumer>;
}
componentDidMount() {
if (this.capturedElements) {
this.ref.current.innerHTML = '';
for(var i = 0; i < this.capturedElements.length; i++) {
const el = this.capturedElements[i];
this.ref.current.appendChild(el);
}
delete this.capturedElements;
return;
}
const div = this.ref.current;
if (!div) {
return;
}
const markupWasFromContext = this.html && div.innerHTML === this.html;
if (markupWasFromContext) { // if not hydrating... TODO: DETECTION ALGORITHM
const keepScripts = true;
const elements = this.oc.$.parseHTML(this.html, keepScripts);
this.oc.$(div).html(elements)
}
if (this.props.captureAs) {
this.saveElements(this.props.captureAs, [...div.childNodes]);
}
const containsUnrenderedComponent = (
div.childNodes.length === 1
&& div.childNodes[0].tagName
&& div.childNodes[0].tagName.toLowerCase() === 'oc-component'
&& div.childNodes[0].getAttribute('data-rendered') !== 'true'
);
if (containsUnrenderedComponent) {
const element = this.oc.$(div.childNodes[0]);
this.oc.renderNestedComponent(element, () => {
if (this.props.captureAs) {
this.saveElements(this.props.captureAs, [...div.childNodes]);
}
});
}
}
}