react-detect-click-outside
Version:
Detects clicks outside React components, and also handles keypresses.
226 lines (151 loc) ⢠6.7 kB
Markdown
# react-detect-click-outside
A lightweight React hook that detects clicks outside elements and triggers a callback. Can also detect keypresses.
š Over 7,600 weekly users (as of June 2022).
š Great for toggling dropdowns!
_**Notice:** This package is looking for maintainers! Due to my professional and personal commitments, I don't have a whole lot of time to devote to maintaining this library. Some users have pointed out a few issues in the [Github repo](https://github.com/zhaluza/react-detect-click-outside/issues) - feel free to take a stab at them!_
<!-- TABLE OF CONTENTS -->
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Requirements](#requirements)
<!-- ABOUT THE PROJECT -->
### Features
- š± š» Detects clicks outside an element and/or keypresses.
- šØ Customizable: disable clicks, disable keypresses, or specify keys that will trigger the callback
- š£ Built with React hooks
- š„ Written in TypeScript
### Installation
Install with [Yarn](https://yarnpkg.com/):
```sh
yarn add react-detect-click-outside
```
Or with [NPM](https://www.npmjs.com/):
```sh
npm i react-detect-click-outside
```
Import into your component like so:
```javascript
import { useDetectClickOutside } from 'react-detect-click-outside';
```
<!-- USAGE EXAMPLES -->
## Usage
Here's an [example](https://codesandbox.io/s/react-detect-click-outside-example-v2osy) of how to use the hook.
This library was built with UI features like dropdowns in mind. Below is a quick and functioning example of how to include it in a dropdown component:
```javascript
const Dropdown = ({ closeDropdown }) => {
const ref = useDetectClickOutside({ onTriggered: closeDropdown });
return (
<div className="dropdown" ref={ref}>
<p>This is a dropdown!</p>
</div>
);
};
```
How to implement the hook inside a function component:
1. Assign the hook to a variable before the component's return statement (above we use `ref`). Pass an empty object into the hook as an argument.
```javascript
const ref = useDetectClickOutside({});
```
2. The object you just passed into the `useDetectClickOutside` hook requires a property called `onTriggered`. The value of `onTriggered` must be a function ā by default, it'll be called anytime a user clicks outside the component or hits the `Escape` key.
In the example above, we used a function called `closeToggle`. This function is passed down from a parent component (let's call it `Container`) and controls a piece of state that determines whether the `Dropdown` component is visible.
Here's a quick, trimmed-down example:
```javascript
const Container = () => {
const [displayDropdown, setDisplayDropdown] = useState(false);
const closeDropdown = () => {
setDisplayDropdown(false);
}
return (
{ displayDropdown && <Dropdown/> }
)
}
```
Now, go ahead and pass your callback into the `useDetectClickOutside` hook!
```javascript
const ref = useDetectClickOutside({ onTriggered: closeDropdown });
```
3. Assign your `ref` constant (or whatever constant you assigned the `useDetectClickOutside` hook to) as a ref to the outermost element returned by your target component.
```javascript
return (
<div className="dropdown" ref={ref}>
<p>This is a dropdown!</p>
</div>
);
```
Here's what the whole component should look like now:
```javascript
const Dropdown = ({ closeDropdown }) => {
const ref = useDetectClickOutside({ onTriggered: closeDropdown });
return (
<div className="dropdown" ref={ref}>
<p>This is a dropdown!</p>
</div>
);
};
```
Congrats! Your `useDetectClickOutside` should now trigger anytime a user clicks outside your component or presses the `Escape` key.
Want to customize your hook? Check out some of the additional options below.
## Options
The object passed into the `useDetectClickOutside` hook accepts the following properties. Note that only `onTriggered` is required.
### `onTriggered` (required)
#### **Type:** `() => void`
A callback function, e.g. one that toggles the visibility of the component. By default, this function is triggered by a click outside the component, and by an `Escape` keyup event.
**Example:**
```javascript
const ref = useDetectClickOutside({ onTriggered: closeDropdown });
```
### `disableClick` (optional)
#### **Type:** `boolean`
When passed to the hook, this option will prevent clicks from triggering the `onTriggered` callback when the component is in the DOM. This option is disabled by default.
**Example:**
```javascript
const ref = useDetectClickOutside({
onTriggered: closeDropdown,
disableClick: true,
});
```
### `disableTouch` (optional)
#### **Type:** `boolean`
When passed to the hook, this option will prevent touch events from triggering the `onTriggered` callback when the component is in the DOM. This option is disabled by default.
**Example:**
```javascript
const ref = useDetectClickOutside({
onTriggered: closeDropdown,
disableTouch: true,
});
```
### `disableKeys` (optional)
#### **Type:** `boolean`
This option will prevent keypresses from triggering the `onTriggered` callback when the component is in the DOM. This option is disabled by default.
**Example:**
```javascript
const ref = useDetectClickOutside({
onTriggered: closeDropdown,
disableKeys: true,
});
```
### `allowAnyKey` (optional)
#### **Type:** `boolean`
This option will let any keypress trigger the `onTriggered` callback when the component is in the DOM - not just the `Escape` key. This option is disabled by default.
**Example:**
```javascript
const ref = useDetectClickOutside({
onTriggered: closeDropdown,
allowAnyKey: true,
});
```
### `triggerKeys` (optional)
#### **Type:** `string[]`
An array of [key values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) that will trigger the `onTriggered` callback.
**Example:**
```javascript
const ref = useDetectClickOutside({
onTriggered: closeDropdown,
triggerKeys: ['Enter', 'Tab', 'x'],
});
```
_Note:_ This option overrides the default hook behavior of triggering the `onTriggered` callback with the `Escape` key. If you still wish to trigger the `onTriggered` function with `Escape`, you need to add it to the array (e.g. `triggerKeys=['Escape', 'Enter']`).
<!-- REQUIREMENTS -->
## Requirements
You must be using [React 16.8.0](https://reactjs.org/blog/2019/02/06/react-v16.8.0.html) or later. In other words, your version of React must support hooks.