@@ -11,6 +11,9 @@ import ownerDocument from './utils/ownerDocument';
11
11
* You can think of it as a declarative `appendChild()`, or jQuery's `$.fn.appendTo()`.
12
12
* The children of `<Portal/>` component will be appended to the `container` specified.
13
13
*/
14
+
15
+ const useCreatePortal = ReactDOM . createPortal !== undefined ;
16
+
14
17
class Portal extends React . Component {
15
18
16
19
static displayName = 'Portal' ;
@@ -26,9 +29,21 @@ class Portal extends React.Component {
26
29
] )
27
30
} ;
28
31
32
+ componentWillMount ( ) {
33
+ if ( useCreatePortal ) {
34
+ this . _mountOverlayTarget ( ) ;
35
+ }
36
+ }
37
+
29
38
componentDidMount ( ) {
30
39
this . _isMounted = true ;
31
40
this . _renderOverlay ( ) ;
41
+ if ( useCreatePortal ) {
42
+ this . _portalContainerNode = getContainer ( this . props . container , ownerDocument ( this ) . body ) ;
43
+ if ( this . _overlayTarget ) {
44
+ this . _portalContainerNode . appendChild ( this . _overlayTarget ) ;
45
+ }
46
+ }
32
47
}
33
48
34
49
componentDidUpdate ( ) {
@@ -45,39 +60,44 @@ class Portal extends React.Component {
45
60
46
61
componentWillUnmount ( ) {
47
62
this . _isMounted = false ;
48
- this . _unrenderOverlay ( ) ;
63
+ if ( ! useCreatePortal ) {
64
+ this . _unrenderOverlay ( ) ;
65
+ }
49
66
this . _unmountOverlayTarget ( ) ;
50
67
}
51
68
52
69
53
70
_mountOverlayTarget = ( ) => {
54
71
if ( ! this . _overlayTarget ) {
55
72
this . _overlayTarget = document . createElement ( 'div' ) ;
56
- this . _portalContainerNode = getContainer ( this . props . container , ownerDocument ( this ) . body ) ;
57
- this . _portalContainerNode . appendChild ( this . _overlayTarget ) ;
73
+ if ( ! useCreatePortal ) {
74
+ this . _portalContainerNode = getContainer ( this . props . container , ownerDocument ( this ) . body ) ;
75
+ this . _portalContainerNode . appendChild ( this . _overlayTarget ) ;
76
+ }
58
77
}
59
78
}
60
79
61
80
_unmountOverlayTarget = ( ) => {
62
- if ( this . _overlayTarget ) {
81
+ if ( this . _overlayTarget && this . _portalContainerNode ) {
63
82
this . _portalContainerNode . removeChild ( this . _overlayTarget ) ;
64
- this . _overlayTarget = null ;
65
83
}
84
+ this . _overlayTarget = null ;
66
85
this . _portalContainerNode = null ;
67
86
}
68
87
69
88
_renderOverlay = ( ) => {
70
-
71
89
let overlay = ! this . props . children
72
90
? null
73
91
: React . Children . only ( this . props . children ) ;
74
92
75
93
// Save reference for future access.
76
94
if ( overlay !== null ) {
77
- this . _mountOverlayTarget ( ) ;
78
- this . _overlayInstance = ReactDOM . unstable_renderSubtreeIntoContainer (
79
- this , overlay , this . _overlayTarget
80
- ) ;
95
+ if ( ! useCreatePortal ) {
96
+ this . _mountOverlayTarget ( ) ;
97
+ this . _overlayInstance = ReactDOM . unstable_renderSubtreeIntoContainer (
98
+ this , overlay , this . _overlayTarget
99
+ ) ;
100
+ }
81
101
} else {
82
102
// Unrender if the component is null for transitions to null
83
103
this . _unrenderOverlay ( ) ;
@@ -93,7 +113,12 @@ class Portal extends React.Component {
93
113
}
94
114
95
115
render ( ) {
96
- return null ;
116
+ if ( useCreatePortal && this . props . children ) {
117
+ let overlay = React . Children . only ( this . props . children ) ;
118
+ return ReactDOM . createPortal ( overlay , this . _overlayTarget ) ;
119
+ } else {
120
+ return null ;
121
+ }
97
122
}
98
123
99
124
getMountNode = ( ) => {
@@ -104,7 +129,9 @@ class Portal extends React.Component {
104
129
if ( ! this . _isMounted ) {
105
130
throw new Error ( 'getOverlayDOMNode(): A component must be mounted to have a DOM node.' ) ;
106
131
}
107
-
132
+ if ( useCreatePortal ) {
133
+ return ReactDOM . findDOMNode ( this ) ;
134
+ }
108
135
if ( this . _overlayInstance ) {
109
136
return ReactDOM . findDOMNode ( this . _overlayInstance ) ;
110
137
}
0 commit comments