react-native-root-siblings
Version:
react native root sibling elements manager
87 lines • 2.85 kB
JavaScript
import React, { useEffect, useState } from 'react';
import { AppRegistry } from 'react-native';
import ChildrenWrapper from './ChildrenWrapper';
import wrapRootComponent from './wrapRootComponent';
let siblingWrapper = sibling => sibling;
function renderSibling(sibling) {
return siblingWrapper(sibling);
}
if (!global.__rootSiblingsInjected && !global.__rootSiblingsDisabled) {
AppRegistry.setWrapperComponentProvider(() => {
return Root;
});
global.__rootSiblingsInjected = true;
}
export function setSiblingWrapper(wrapper) {
siblingWrapper = wrapper;
}
const { Root, manager: defaultManager } = wrapRootComponent(ChildrenWrapper, renderSibling);
let uuid = 0;
const managerStack = [defaultManager];
const inactiveManagers = new Set();
function getActiveManager() {
for (let i = managerStack.length - 1; i >= 0; i--) {
const manager = managerStack[i];
if (!inactiveManagers.has(manager)) {
return manager;
}
}
return defaultManager;
}
export default class RootSiblingsManager {
constructor(element, callback) {
this.id = `root-sibling-${uuid + 1}`;
this.manager = getActiveManager();
this.manager.update(this.id, element, callback);
uuid++;
}
update(element, callback) {
this.manager.update(this.id, element, callback);
}
destroy(callback) {
this.manager.destroy(this.id, callback);
}
}
export function RootSiblingParent(props) {
const { inactive } = props;
const [sibling] = useState(() => {
const { Root: parentRoot, manager: parentManager } = wrapRootComponent(ChildrenWrapper, renderSibling);
managerStack.push(parentManager);
if (inactive) {
inactiveManagers.add(parentManager);
}
return {
Root: parentRoot,
manager: parentManager
};
});
useEffect(() => {
return () => {
if (sibling) {
const index = managerStack.indexOf(sibling.manager);
if (index > 0) {
managerStack.splice(index, 1);
}
}
};
}, [sibling]);
if (inactive && sibling && !inactiveManagers.has(sibling.manager)) {
inactiveManagers.add(sibling.manager);
}
else if (!inactive && sibling && inactiveManagers.has(sibling.manager)) {
inactiveManagers.delete(sibling.manager);
}
const Parent = sibling.Root;
return <Parent>{props.children}</Parent>;
}
export function RootSiblingPortal(props) {
const [sibling] = useState(() => new RootSiblingsManager(null));
sibling.update(props.children);
useEffect(() => {
if (sibling) {
return () => sibling.destroy();
}
}, [sibling]);
return null;
}
//# sourceMappingURL=RootSiblingsManager.js.map