import { Component, createRef } from 'react'; import PropTypes from 'prop-types'; class Toggle extends Component { state = { on: false, } wrapper = createRef() escapeListener = event => { if (event.keyCode === 27) { this.toggle(); } } clickListener = event => { const { wrapper } = this; const clickedOutside = !wrapper.current.contains(event.target); if (clickedOutside) { this.toggle(); } } toggle = e => { if (e) { e.stopPropagation(); } if (!this.state.on) { window.addEventListener('click', this.clickListener); window.addEventListener('keyup', this.escapeListener); } else { window.removeEventListener('click', this.clickListener); window.removeEventListener('keyup', this.escapeListener); } this.setState(prevState => ({ on: !prevState.on })); } render () { const { on } = this.state; const { toggle, wrapper } = this; const passedProps = { // is the Toggle triggered or not... on, // Use this to toggle it out toggle, // Add this ref to your component to click-out works! wrapper, }; return this.props.children({ ...passedProps }); } } Toggle.propTypes = { children: PropTypes.func.isRequired, }; export default Toggle;