Handling "clicks outside" in ReactJS
A very common component in (web-)applications is a popup/modal/dialog. You want to interact with the user without navigating away from the current view. How to create such a component will be the subject of another blogpost or two - as no framework to date supports this out of the box.
After the modal/dialog/whatever is popped up the expectation is that when clicked/tapped outside the thing closes again.
In order to make this work in ReactJS we have to hook into the actual DOM like so:
import React, {Component} from "react";
import PropTypes from "prop-types";
export default class ClickOutsideWrapper extends Component {
static propTypes = {
onClickOutside: PropTypes.func,
children: PropTypes.element.isRequired
}
componentDidMount() {
document.addEventListener('mousedown', this.handleClickOutside, true);
document.addEventListener('touchstart', this.handleClickOutside, true);
}
componentWillUnmount() {
document.removeEventListener('mousedown', this.handleClickOutside);
document.removeEventListener('touchstart', this.handleClickOutside);
}
handleClickOutside = (event) => {
if (this.container && !this.container.contains(event.target)) {
event.preventDefault()
event.stopPropagation()
this.props.onClickOutside()
}
}
render() {
return (
<div ref={(element) => this.container = element}>
{this.props.children}
</div>
)
}
}
To use this component you wrap it around the thing popping up:
<ClickOutsideWrapper onClickOutside={this.onClickedOutside}>
<YourPopupComponent/>
</ClickOutsideWrapper>
This code is based on this SO answer: https://stackoverflow.com/a/42234988/26496