I'm working on a dropdown and want it to close when I click outside of it. What I've done works on Chrome, on all the Android devices I tried with and with all of the iPhones on iOS 13 but doesn't work on older devices. I tried to do it in different ways, and none of them works... Here is my code if anyone wants to help!
const wrapperRef = useRef(null)
const [scrollToggle, changeScrollToggle] = useState(false)
const alteredPriceRange = [defaultValue].concat(priceRange)
const slideToggle = () => {
if (scrollToggle) {
changeScrollToggle(false)
} else {
changeScrollToggle(true)
}
}
const handleClickOutside = (e) => {
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
changeScrollToggle(false)
} else {
}
}
const optionSorter = (price) => {
return price === 'min' || price === 'max' ? <>{`No ${price}`}</> : <><span>£</span> {price}</>
}
const selectedInput = () => {
return currentValue === '' ? defaultValue : currentValue
}
useEffect(() => {
const setHeight = slideRef => {
if (scrollToggle) {
slideRef.current.style.height = `${slideRef.current.firstChild.getBoundingClientRect().height}px`
} else {
slideRef.current.style.height = 0
}
}
setHeight(slideRef)
}, [scrollToggle])
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [])
return (
<Fragment>
<div ref={wrapperRef} className={`dropdown-wrapper ${scrollToggle ? 'dropdown-active' : ''}`}>
<div
id={`dropdown-selector-${idValue}`}
className='dropdown-field'
onClick={() => { slideToggle() }}
>
<p>
<span className='currency'>£</span><span className='money'>
{selectedInput()}
</span>
</p>
<span className='caret'>
<img src={caret} alt='caret' />
</span>
</div>
<div className='scroll-content-wrapper'>
<div className='scroll-block' ref={slideRef}>
<Picklist className={'area'}>
{alteredPriceRange.map((price, i) =>
<div
id={`${idValue}-price-option-${i}`}
key={i}
onClick={(e) => {
selectClick(e, price, defaultValue)
slideToggle()
}}
>
{optionSorter(price)}
</div>
)
}
</Picklist>
</div>
</div>
</div>
</Fragment>
)
}
Thank you
Try to use touchstart event
The touchstart event occurs when the user touches an element.
Note: The touchstart event will only work on devices with a touch screen.
const handleClickOutside = (e) => {
if (e.type === "touchstart") e.preventDefault(); // <- new line
if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
changeScrollToggle(false)
} else {
}
}
// ...
useEffect(() => {
document.addEventListener('touchstart', handleClickOutside) // <- new line
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('touchstart', handleClickOutside) // <- new line
document.removeEventListener('mousedown', handleClickOutside)
}
}, [])
NOTE: Didn't test this code!