import React from 'react';
import PropTypes from 'prop-types';
/* eslint-disable import/no-extraneous-dependencies */
import ReactDOM from 'react-dom';
/* eslint-enable import/no-extraneous-dependencies */
const isReact16 = ReactDOM.createPortal !== undefined;
export default class InlinePortal extends React.Component {
static propTypes = {
children: PropTypes.node,
show: PropTypes.bool
};
static defaultProps = {
children: null,
show: false
};
componentDidMount() {
this.renderFallbackPortal();
}
componentWillReceiveProps(nextProps) {
if (nextProps.show) {
this.createNode(nextProps);
}
if (nextProps.show === false && this.props.show === true) {
this.closePortal();
}
}
componentDidUpdate() {
this.renderFallbackPortal();
}
componentWillUnmount() {
this.closePortal();
}
createNode(props) {
if (!this.node) {
this.node = document.createElement('div');
this.node.className = `${props.className || ''} portal`.trim();
document.body.appendChild(this.node);
}
}
closePortal() {
if (this.node) {
document.body.removeChild(this.node);
}
this.node = null;
}
/* eslint-disable consistent-return */
renderFallbackPortal = () => {
if (!isReact16) {
if (this.props.show) {
this.createNode(this.props);
return ReactDOM.unstable_renderSubtreeIntoContainer(
this,
this.props.children,
this.node
);
}
this.closePortal();
}
};
/* eslint-enable consistent-return */
render() {
if (!this.props.show || !isReact16) {
return null;
}
return ReactDOM.createPortal(
this.props.children,
this.node
);
}
}
|