| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- import { useCallback, useEffect, useRef, useState } from 'react'
- import { findDOMNode } from 'react-dom'
- export default function useDropdown(defaultOpen = false) {
- const [open, setOpen] = useState(defaultOpen)
- // store the dropdown node for use in the "click outside" event listener
- const ref = useRef(null)
- // react-bootstrap v0.x passes `component` instead of `node` to the ref callback
- const handleRef = useCallback(
- component => {
- if (component) {
- // eslint-disable-next-line react/no-find-dom-node
- ref.current = findDOMNode(component)
- }
- },
- [ref]
- )
- // prevent a click on the dropdown toggle propagating to the original handler
- const handleClick = useCallback(event => {
- event.stopPropagation()
- }, [])
- // handle dropdown toggle
- const handleToggle = useCallback(value => {
- setOpen(value)
- }, [])
- // close the dropdown on click outside the dropdown
- const handleDocumentClick = useCallback(
- event => {
- if (ref.current && !ref.current.contains(event.target)) {
- setOpen(false)
- }
- },
- [ref]
- )
- // add/remove listener for click anywhere in document
- useEffect(() => {
- if (open) {
- document.addEventListener('mousedown', handleDocumentClick)
- }
- return () => {
- document.removeEventListener('mousedown', handleDocumentClick)
- }
- }, [open, handleDocumentClick])
- // return props for the Dropdown component
- return { ref: handleRef, onClick: handleClick, onToggle: handleToggle, open }
- }
|