Allow passing an array of refs to useClickAway
Is your feature request related to a problem? Please describe. For my use case I have a button that opens a modal. Once the modal is open, I want clicking away to close the modal, but if I click on the modal toggle button, I get two conflicting commands - from the modal useClickAway event and from the button's onClick event.
Describe the solution you'd like If I could pass an array of refs then I could prevent the behavior described above by passing a ref for the modal as well as the button.
Describe alternatives you've considered I had tried making the modal toggle button only fire when the modal is closed, however that still ran into a race-condition, even when setting the mouse events to ['mouseup', 'touchend']. Another alternate solution would be to use a setTimeout, however I'd prefer to not use that.
Oh man, I can't tell you the number of times this has happened to me outside of this library! I'll try to fix this weekend, feel the pain!
@blnk-space any luck? I've run into a second instance where this would be nice: I'm using a portal and need to ref the portal as well. May try to timebox a solution tomorrow
PR: https://github.com/streamich/react-use/pull/1125
For those who are looking for a solution to this problem You can check if your dropdown is already open and then close it
Example:
Wrong:
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const ref = useRef();
useClickAway(ref, () => setIsDropdownOpen(false));
<div className="container" ref={ref}>
<div className="dropdown" />
</div>
Correct:
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const ref = useRef();
useClickAway(ref, () => isDropdownOpen ? setIsDropdownOpen(false) : null);
<div className="container" ref={ref}>
<div className="dropdown" />
</div>
I'm facing exactly this problem and it always takes like 3-4 additional internal state checking just to close a modal correctly, especially when I have to move modal to portal.
Really looking forward to the PR.
Many thanks.
I have a similar use case, and for now, I'm using a ref on the element to ignore to work around it.
If the element contains children you'll need to prevent clicks on them, for example using pointer-events: none.
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const navRef = useRef(null);
const navButtonRef = useRef(null);
useClickAway(navRef, (event) => {
const clickedNavButton = event.target === navButtonRef.current;
if (!clickedNavButton) {
setIsSidebarOpen(false);
}
});
Hi, everyone. I added this feature to useClickAway (https://github.com/streamich/react-use/pull/2593). Waiting review.
@matthova I saw your PR, but I don't understand why it still hasn't merged.