Meet npm Pro: unlimited public & private packages + package-based permissions.Learn more »

react-click-outside-listener

2.0.0 • Public • Published

ci codecov downloads node npm MIT npm bundle size Conventional Commits

react-click-outside-listener

Wrapping component to register click outside.

Installation

As any other npm package react-click-outside-listener can be added to your project by following command:

npm i -S react-click-outside-listener

It requires any version of react with new context API support as peer dependency, so it should be installed as well.

npm i -S react

Quick start

Nothing is easier than use ClickOutsideListener component - just wrap your content with it:

import { ClickOutsideListener } from 'react-click-outside-listener';
 
const Parent = () => {
    const handleClickOutside = ...;
 
    return (
        <ClickOutsideListener onClickOutside={ handleClickOutside }>
            <div>Just put your content inside</div>
            <div>You can put several elements, if you need</div>
            <div>ClickOutsideListener component will call listener only if none of those clicked</div>
            <div>
                <div>Of course we can nest items</div>
            </div>
        </ClickOutsideListener>
    );
}

It is only possible to track clicks on html elements, so children should be html elements or React components forwarding refs:

const Child = React.forwardRef((props, ref) => (
    <div ref={ ref }>
        We should attach ref to html container
    </div>
));
 
const Parent = () => {
    ...
 
    return (
        <ClickOutsideListener onClickOutside={ handleClickOutside }>
            <Child />
        </ClickOutsideListener>
    );
}

If you need to support custom properties for refs or want to track selected items, use render prop as a child:

const Parent = () => {
    return (
        <ClickOutsideListener onClickOutside={ handleClickOutside }>
            {refs => (
                <div>
                    Click here to invoke callback
                    <div ref={ refs(0) }>
                        No callback when click here
                    </div>
                    <div>Beware callbacks</div>
                    <div ref={ refs(1) }>
                        Another safe zone
                    </div>
                </div>
            )}
        </ClickOutsideListener>
    );
}

renderProp argument can be also used as regular ref:

const Component = () => {
    return (
        <ClickOutsideListener onClickOutside={ handleClickOutside }>
            {ref => (
                <div>
                    <div ref={ ref }>
                        No callback when click here
                    </div>
                </div>
            )}
        </ClickOutsideListener>
    );
}

Let's consider small example with dropdown menu:

const Menu = ({ label, items }) => {
    const [ isShown, setIsShown ] = useState(false);
    const toggleMenu = useCallback(
        () => setIsShown(isShown => !isShown),
        []
    );
    const handleClickOutside = useCallback(
        () => setIsShown(false),
        []
    );
 
    return (
        <ul className="menu">
            <ClickOutsideListener onClickOutside={ handleClickOutside }>
                {refs => (
                    <React.Fragment>
                        <button
                            className="menu__trigger"
                            onClick={ toggleMenu }
                            ref={ refs(0) }
                        >
                            { label }
                        </button>
                        <Dropdown
                            items={ items }
                            wrapperRef={ refs(1) }
                            />
                    </React.Fragment>
                )}
            </ClickOutsideListener>
        </ul>
    );
}
 
...
 
const Dropdown = ({ items, wrapperRef }) => (
    <ul
        className='dropdown'
        ref={ wrapperRef }
    >
        { items.map(
            ({ id, label, action }) => (
                <li
                    key={ id || label }
                    className="dropdown__item"
                    onClick={ action }
                >
                    { label }
                </li>
            )
        ) }
    </ul>
);

Hook

react-click-outside-listener package also exposes hook to achieve the same functionality. It returns refs item similar to ClickOutsideListener renderProp argument. It cab be used to set several refs or only one:

import { useClickOutsideListener } from 'react-click-outside-listener';
 
const Component = () => {
    const refs = useClickOutsideListener(
        () => { ... }
    );
 
    // several refs
    return (
        <div>
            Click here to invoke callback
            <div ref={ refs(0) }>
                No callback when click here
            </div>
            <div>Beware callbacks</div>
            <div ref={ refs(1) }>
                Another safe zone
            </div>
        </div>
    );
}
 
// or
 
const Component = () => {
    const ref = useClickOutsideListener(
        () => { ... }
    );
 
    // one ref
    return (
        <div>
            <div ref={ ref }>
                No callback when click here
            </div>
        </div>
    );
}

Install

npm i react-click-outside-listener

DownloadsWeekly Downloads

1

Version

2.0.0

License

MIT

Unpacked Size

12.9 kB

Total Files

8

Last publish

Collaborators

  • avatar