У меня есть компонент с пользовательским раскрывающимся списком, и функция закрытия раскрывающегося списка при нажатии в любом месте за пределами компонента работает так, как должна (см. Ниже):
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const dropdownRef = useRef(null);
useEffect(() => {
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setIsDropdownOpen(false)
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => { //cleanup function
document.removeEventListener("mousedown", handleClickOutside);
};
});
const toggleDropDown = () => {
setIsDropdownOpen(!isDropdownOpen)
}
return (
<div onClick={toggleDropDown}> click here
{isDropdownOpen && (
<div ref={dropdownRef}>
<div onClick={handleOption2}>Option 1</div>
<div onClick={handleOption2}>Option 2</div>
</div>
)}
</div>
)
Когда я динамически создаю компонент для каждого элемента в массиве, вместо этого я использую массив ссылок и пишу функцию внешнего клика, как показано ниже:
const [allDropdownOpen, setAllDropdownOpen] = useState([]);
const dropdownRefs = useRef([]);
// set false dropdown states for all items in array (the array is fetched through an API call)
useEffect(() => {
if(fetchedArray) {
let arr = [];
fetchedArray.forEach(() => arr.push(false));
setAllDropdownOpen(arr)
}
}, [fetchedArray])
useEffect(() => {
let arr = [];
if(fetchedArray) {
fetchedArray.forEach(() => arr.push(false)); //create false states for all items in array
}
const handleClickOutside = (e) => {
if(dropdownRefs.current.some(ref => ref && !ref.contains(e.target))) {
setAllDropdownOpen(arr) //close all dropdowns
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => { //cleanup function
document.removeEventListener("mousedown", handleClickOutside);
};
});
const toggleDropDown = (index) => {
//change dropdown state for selected item
const arr = [...allDropdownOpen];
arr[index] = !arr[index];
setAllDropdownOpen([...arr]);
}
return (
<div>
{fetchedArray.map((data, i) => (
<div
onClick={() => toggleDropDown(i)}
ref={el => (dropdownRefs.current[i] = el)}
>
click here
{allDropdownOpen[i] && (
<div>
<div onClick={handleOption2}>Option 1</div>
<div onClick={handleOption2}>Option 2</div>
</div>
)}
</div>
)}
</div>
)
Хотя это работает и раскрывающиеся списки закрываются, проблема, с которой я сталкиваюсь сейчас, заключается в том, что когда я выбираю параметр в раскрывающемся списке Вариант 1 или Вариант 2, он не выполняет handleOption1
или handleOption2
. Он просто закрывает все выпадающие списки.
Я подтвердил, что параметры на самом деле активны и выполняются, когда я удаляю хук useEffect
с помощью функции handleOutsideClick
, поэтому я знаю, что ошибка оттуда.
Как избежать этого и правильно нацелить раскрывающийся список выбранного элемента массива?