Skip to content

Commit 9b6e3c2

Browse files
authored
fix(Portal): ignore document click if no node or portal (#823)
* refactor(Portal): consolidate !open checks in renderPortal * fix(portal): clean up event handlers when re-rendering * fix(Portal): ignore document click if no node or portal
1 parent 0185032 commit 9b6e3c2

1 file changed

Lines changed: 15 additions & 8 deletions

File tree

src/addons/Portal/Portal.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,10 @@ class Portal extends Component {
122122

123123
static _meta = _meta
124124

125+
state = {}
126+
125127
componentDidMount() {
126-
if (this.state.open) {
127-
this.renderPortal()
128-
}
128+
this.renderPortal()
129129
}
130130

131131
componentDidUpdate(prevProps, prevState) {
@@ -134,9 +134,7 @@ class Portal extends Component {
134134
// within this method.
135135

136136
// If the portal is open, render (or re-render) the portal and child.
137-
if (this.state.open) {
138-
this.renderPortal()
139-
}
137+
this.renderPortal()
140138

141139
if (prevState.open && !this.state.open) {
142140
debug('portal closed')
@@ -159,8 +157,8 @@ class Portal extends Component {
159157
handleDocumentClick = (e) => {
160158
const { closeOnDocumentClick, closeOnRootNodeClick } = this.props
161159

162-
// If event happened in the portal, ignore it
163-
if (this.portal.contains(e.target)) return
160+
// If not mounted, no portal, or event happened in the portal, ignore it
161+
if (!this.node || !this.portal || this.portal.contains(e.target)) return
164162

165163
if (closeOnDocumentClick || (closeOnRootNodeClick && this.node.contains(e.target))) {
166164
debug('handleDocumentClick()')
@@ -320,6 +318,9 @@ class Portal extends Component {
320318
}
321319

322320
renderPortal() {
321+
if (!this.state.open) return
322+
debug('renderPortal()')
323+
323324
const { children, className } = this.props
324325

325326
this.mountPortal()
@@ -329,6 +330,12 @@ class Portal extends Component {
329330

330331
this.node.className = className || ''
331332

333+
// when re-rendering, first remove listeners before re-adding them to the new node
334+
if (this.portal) {
335+
this.portal.removeEventListener('mouseleave', this.handlePortalMouseLeave)
336+
this.portal.removeEventListener('mouseover', this.handlePortalMouseOver)
337+
}
338+
332339
ReactDOM.unstable_renderSubtreeIntoContainer(
333340
this,
334341
Children.only(children),

0 commit comments

Comments
 (0)