✅ – ✅ – dmikester1 – 16-36 Sep 26

I have an OutsideClickTrigger hook I have found that I am utilizing to hide a filter menu whenever the user clicks outside the menu. There is a filters button that I am using to show the filters menu like this: onClick={() => setShowFilters(!showFilters)}. Now the issue is that when the filters menu is open, and I click on the filters button again to close it, it does not work or maybe it closes it quickly and then OutsideClickTrigger gets run and it shows it again. Last time I was able to fix this by wrapping the button and the menu in the hook component. That won't work this time because of the structure of my html. I'm thinking I somehow need to also pass the button element into that hook so it checks if that was the element clicked.
Solution:
Message Not Public
Sign In & Join Server To View
D
dmikester1203d ago
Here is my OutsideClickTrigger hook component:
import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';

/**
* Hook that alerts clicks outside of the passed ref
*/
const useOutsideTrigger = (ref, onClick) => {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
onClick();
}
}
// Bind the event listener
document.addEventListener('mousedown', handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref]);
};

/**
* Component that alerts if you click outside of it
*/
const OutsideTrigger = (props) => {
const wrapperRef = useRef(null);
useOutsideTrigger(wrapperRef, props.onClick);

return <div ref={wrapperRef}>{props.children}</div>;
};

OutsideTrigger.propTypes = {
children: PropTypes.element.isRequired
};

export default OutsideTrigger;
import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';

/**
* Hook that alerts clicks outside of the passed ref
*/
const useOutsideTrigger = (ref, onClick) => {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
onClick();
}
}
// Bind the event listener
document.addEventListener('mousedown', handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener('mousedown', handleClickOutside);
};
}, [ref]);
};

/**
* Component that alerts if you click outside of it
*/
const OutsideTrigger = (props) => {
const wrapperRef = useRef(null);
useOutsideTrigger(wrapperRef, props.onClick);

return <div ref={wrapperRef}>{props.children}</div>;
};

OutsideTrigger.propTypes = {
children: PropTypes.element.isRequired
};

export default OutsideTrigger;
In this section: if (ref.current && !ref.current.contains(event.target)) { onClick(); } I think I also need to check if the button was clicked.
UU
Unknown User203d ago
D
dmikester1203d ago
I thought this was kind of a "click away component". I am wrapping my stuff in it like this: <OutsideTrigger onClick={() => setShowFilters(false)}> I can remove the prop types 🙂
UU
Unknown User203d ago
D
dmikester1203d ago
So you are saying rewrite the logic in useOutsideTrigger ?
UU
Unknown User203d ago
D
dmikester1203d ago
OK, so I would wrap my menu and my button with that component?
UU
Unknown User203d ago
D
dmikester1203d ago
Cool, I'll give it a try and report back!
UU
Unknown User203d ago
D
dmikester1203d ago
I renamed it from modal, but this is how I wrapped my filters menu: <OutsideClickHook onClickAway={() => setShowFilters(false)}> when I click outside the menu, it does not dissapear
UU
Unknown User203d ago
D
dmikester1203d ago
<OutsideClickHook onClickAway={() => setShowFilters(false)}>
<div
className={`column-filters ${
showFilters ? 'show' : 'hide'
}`}
>
<h4 className={'title'}>Filters</h4>
...
<OutsideClickHook onClickAway={() => setShowFilters(false)}>
<div
className={`column-filters ${
showFilters ? 'show' : 'hide'
}`}
>
<h4 className={'title'}>Filters</h4>
...
and above that section:
<button
className={`btn ${
currentColumnFilters
? 'btn-outline-success'
: 'btn-outline-secondary'
}`}
onClick={() => setShowFilters(!showFilters)}
>
<FontAwesomeIcon
icon={'fa-regular fa-filter' as IconProp}
/>{' '}
Filter{' '}
</button>
<button
className={`btn ${
currentColumnFilters
? 'btn-outline-success'
: 'btn-outline-secondary'
}`}
onClick={() => setShowFilters(!showFilters)}
>
<FontAwesomeIcon
icon={'fa-regular fa-filter' as IconProp}
/>{' '}
Filter{' '}
</button>
UU
Unknown User203d ago
D
dmikester1203d ago
are those bootstrap classes or something different?
UU
Unknown User203d ago
D
dmikester1203d ago
ok
UU
Unknown User203d ago
D
dmikester1203d ago
i'd ideally like to fade it in/out
Solution
UU
Unknown User203d ago
D
dmikester1203d ago
oh i see i'll try that Is this div meant to take up the entire page? <div onClick={onClickAway} className="flex h-full w-full flex-col items-center justify-center bg-black/50" >
UU
Unknown User203d ago
D
dmikester1203d ago
so wherever i click, i will be clicking that div?
UU
Unknown User203d ago
D
dmikester1203d ago
I think that is my issue gonna be tricky to figure out the positioning of my menu with that though
D
dmikester1203d ago
No description
D
dmikester1203d ago
The filters menu is under the Filter button
UU
Unknown User203d ago
D
dmikester1203d ago
not finding one, but something like this?
{showFilters && (
<>
<div className={'full-overlay z-1'} onClick={() => setShowFilters(false)}></div>
<div className={'column-filters z-2'} onClick={ev => ev.stopPropagation()}>
<h4 className={'title'}>Filters</h4>
{showFilters && (
<>
<div className={'full-overlay z-1'} onClick={() => setShowFilters(false)}></div>
<div className={'column-filters z-2'} onClick={ev => ev.stopPropagation()}>
<h4 className={'title'}>Filters</h4>
oh i wasn't gonna use children something like that? think I got it!!! I had to set position: fixed on that overlay and now it is going full width and height.
UU
Unknown User203d ago
D
dmikester1203d ago
Thank you so much igaul! That was a tricky one! Never would have thought of that stopPropagation trick.
UU
Unknown User202d ago