A React component to handle clicking outside of an element.
- Wrap a single element or multiple elements to watch for clickout behavior
- Ignore one or more elements (clickout behavior won't be triggered) by adding them to the
ignoredElements
prop - Enable or disable the clickout behavior on the fly with the
enabled
prop
yarn add react-clickout-handler
or
npm install --save react-clickout-handler
import React from 'react'
import ClickOutHandler from 'react-clickout-handler'
const MyComponent = () => {
const handleClickOut = () => {
console.log('clicked out!')
}
return (
<ClickOutHandler onClickOut={handleClickOut}>
<div className='modal'>
This is a modal! Click outside to close it.
</div>
</ClickOutHandler>
)
}
Prop | Type | Required | Default | Description |
---|---|---|---|---|
children |
`Node | ({ [string]: Ref }) => any` | true | |
enabled |
boolean |
false | true |
Enables or disables the clickout behavior. This can be useful to ensure the onClickOut callback is only executed when you want it to be. |
events |
string[] |
false | ['mousedown', 'touchstart'] |
Allows for specifying custom events to trigger the onClickOut callback |
ignoredElements |
Object[] |
false | [] |
An array of refs for elements to exclude from triggering the clickout behavior |
refProp |
string |
false | ref |
Specify a prop name to use for getting a ref to the wrapped component. Useful if you need to get the ref for a "composed" component, or if you're using something like styled-components, which requires use of innerRef to get the ref of a styled component. |
wrapWith |
ElementType |
false | null |
Specify what type of element to wrap the children with. Can be a React component or string such as div . If this prop is not provided, the ClickOutHandler component will either clone the child element (if single child) or wrap the children in a div (if multiple children). |
onClickOut |
(ev: Event) => any |
true | Function to be called when the clickout behavior is triggered. Receives the click event as an argument. |
If there are any elements outside of your ClickOutHandler component that you do not want to trigger the clickout behavior when clicked, you can pass a ref to the ignoredElements
prop.
import React, { Component } from 'react'
import ClickOutHandler from 'react-clickout-handler'
export default class MyComponent extends Component {
state = {
data: ''
}
handleChange = (data) => {
this.setState({ data })
}
save = () => {
apiCall(this.state.data)
}
setRef = (el) => { this.saveButton = el }
render() {
return (
<div id='my-app'>
<ClickOutHandler
ignoredElements={[this.saveButton]}
onClickOut={handleClickOut}
>
<SomeComponent onChange={this.handleChange} />
</ClickOutHandler>
<button ref={this.setRef} onClick={this.save}>
Save
</button>
</div>
)
}
}
ClickOutHandler
relies on having a ref to its immediate child. If the child is unable to directly accept a ref
prop, there are two options:
Use the refProp
prop
import React from 'react'
import ClickOutHandler from 'react-clickout-handler'
import styled from 'styled-components'
const MyDiv = styled.div`
background-color: red;
`
const handleClickOut = () => {
console.log('You clicked me!')
}
const MyComponent = () => (
<ClickOutHandler onClickOut={handleClickOut} refProp='innerRef'>
<MyDiv />
</ClickOutHandler>
)
Pass a function as the child
import React from 'react'
import ClickOutHandler from 'react-clickout-handler'
import styled from 'styled-components'
const MyDiv = styled.div`
background-color: red;
`
const handleClickOut = () => {
console.log('You clicked me!')
}
const MyComponent = () => (
<ClickOutHandler onClickOut={handleClickOut}>
{({ ref }) => <MyDiv innerRef={ref} />}
</ClickOutHandler>
)
MIT