@difizen/mana-react
Version:
95 lines (74 loc) • 2.36 kB
text/typescript
import type * as React from 'react';
import * as ReactDOM from 'react-dom';
import type { Root } from 'react-dom/client';
// Let compiler not to search module usage
const fullClone = {
...ReactDOM,
} as typeof ReactDOM & {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED?: {
usingClientEntryPoint?: boolean;
};
createRoot?: CreateRoot;
};
type CreateRoot = (container: ContainerType) => Root;
const { version, render: reactRender, unmountComponentAtNode } = fullClone;
let createRoot: CreateRoot|undefined;
try {
const mainVersion = Number((version || '').split('.')[0]);
if (mainVersion >= 18) {
({ createRoot } = fullClone);
}
} catch (e) {
// Do nothing;
}
function toggleWarning(skip: boolean) {
const { __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED } = fullClone;
if (
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED &&
typeof __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED === 'object'
) {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint =
skip;
}
}
const MARK = '__rc_react_root__';
// ========================== Render ==========================
type ContainerType = (Element | DocumentFragment) & {
[MARK]?: Root;
};
function modernRender(node: React.ReactElement, container: ContainerType) {
toggleWarning(true);
const root = container[MARK] || createRoot!(container);
toggleWarning(false);
root.render(node);
container[MARK] = root;
}
function legacyRender(node: React.ReactElement, container: ContainerType) {
reactRender(node, container);
}
export function render(node: React.ReactElement, container: ContainerType) {
if (createRoot) {
modernRender(node, container);
return;
}
legacyRender(node, container);
}
// ========================= Unmount ==========================
async function modernUnmount(container: ContainerType) {
// Delay to unmount to avoid React 18 sync warning
return Promise.resolve().then(() => {
container[MARK]?.unmount();
delete container[MARK];
return
});
}
function legacyUnmount(container: ContainerType) {
unmountComponentAtNode(container);
}
export async function unmount(container: ContainerType) {
if (createRoot !== undefined) {
// Delay to unmount to avoid React 18 sync warning
return modernUnmount(container);
}
legacyUnmount(container);
}