dmikester1
dmikester110mo ago

✅ – ✅ – 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
Jump to solution
34 Replies
dmikester1
dmikester110mo 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.
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo 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 🙂
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
So you are saying rewrite the logic in useOutsideTrigger ?
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
OK, so I would wrap my menu and my button with that component?
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
Cool, I'll give it a try and report back!
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo 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
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo 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>
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
are those bootstrap classes or something different?
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
ok
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
i'd ideally like to fade it in/out
Solution
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo 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" >
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
so wherever i click, i will be clicking that div?
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo ago
I think that is my issue gonna be tricky to figure out the positioning of my menu with that though
dmikester1
dmikester110mo ago
No description
dmikester1
dmikester110mo ago
The filters menu is under the Filter button
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
dmikester1
dmikester110mo 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.
reactibot
reactibot10mo ago
This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/902647189120118794/1156268044486705274
reactibot
reactibot10mo ago
This question has an answer! Thank you for helping 😄 If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/902647189120118794/1156268044486705274
dmikester1
dmikester110mo ago
Thank you so much igaul! That was a tricky one! Never would have thought of that stopPropagation trick.
Unknown User
Unknown User10mo ago
Message Not Public
Sign In & Join Server To View
reactibot
reactibot9mo ago
This thread hasn’t had any activity in 36 hours, so it’s now locked. Threads are closed automatically after 36 hours. If you have a followup question, you may want to reply to this thread so other members know they're related. https://discord.com/channels/102860784329052160/902647189120118794/1156268044486705274