|
1 | | -import { Component } from 'react' |
| 1 | +import { useRef, useState } from 'react' |
2 | 2 | import PropTypes from 'prop-types' |
3 | | -import ReactDOM from 'react-dom' |
4 | | -import canUseDom from '../../lib/canUseDom' |
| 3 | +import { createPortal } from 'react-dom' |
| 4 | +import { useIsomorphicLayoutEffect } from '../../hooks' |
5 | 5 |
|
6 | | -let portalContainer |
| 6 | +// Based on https://github.com/mantinedev/mantine/blob/master/src/mantine-core/src/Portal/Portal.tsx |
| 7 | +const Portal = props => { |
| 8 | + const { children } = props |
7 | 9 |
|
8 | | -export default class Portal extends Component { |
9 | | - constructor() { |
10 | | - super() |
| 10 | + const [mounted, setMounted] = useState(false) |
| 11 | + const ref = useRef() |
11 | 12 |
|
12 | | - // This fixes SSR |
13 | | - if (!canUseDom) return |
| 13 | + useIsomorphicLayoutEffect(() => { |
| 14 | + setMounted(true) |
14 | 15 |
|
15 | | - if (!portalContainer) { |
16 | | - portalContainer = document.createElement('div') |
17 | | - portalContainer.setAttribute('evergreen-portal-container', '') |
18 | | - document.body.appendChild(portalContainer) |
19 | | - } |
20 | | - } |
| 16 | + ref.current = document.createElement('div') |
| 17 | + ref.current.setAttribute('evergreen-portal-container', '') |
21 | 18 |
|
22 | | - componentDidMount() { |
23 | | - this.el = document.createElement('div') |
24 | | - portalContainer.appendChild(this.el) |
25 | | - this.forceUpdate() |
26 | | - } |
| 19 | + document.body.appendChild(ref.current) |
27 | 20 |
|
28 | | - componentWillUnmount() { |
29 | | - portalContainer.removeChild(this.el) |
30 | | - } |
| 21 | + return () => { |
| 22 | + document.body.removeChild(ref.current) |
| 23 | + } |
| 24 | + }, []) |
31 | 25 |
|
32 | | - render() { |
33 | | - if (!this.el) return null |
34 | | - return ReactDOM.createPortal(this.props.children, this.el) |
| 26 | + if (!mounted) { |
| 27 | + return null |
35 | 28 | } |
| 29 | + |
| 30 | + return createPortal(children, ref.current) |
36 | 31 | } |
37 | 32 |
|
38 | 33 | Portal.propTypes = { |
39 | 34 | children: PropTypes.node.isRequired |
40 | 35 | } |
| 36 | + |
| 37 | +export default Portal |
0 commit comments