I have a component Dropdowns which renders a group of dropdown menus.
When multiple menus are rendered, clicking on a dropdown opens all of them at the same time. How can I make sure I only toggle the active state of one dropdown?
Options prop determines how many Dropdowns get rendered. id is simply for development so I can find it in devtools easier, in the case I have multiple Dropdowns on one page.
import React, { useState } from 'react';
import * as style from './Dropdown.module.css';
const Dropdown = (props) => {
const { options, id } = props;
const [active, setActive] = useState(false);
const [selectedOption, setSelectedOption] = useState(0);
const handleActive = () => {
setActive(!active);
};
const setSelectedThenCloseDropdown = (index, filter, item) => {
filter.handler(item);
setSelectedOption(index);
setActive(!active);
};
const handleKeyDown = (index, filter, item) => (e) => {
switch (e.key) {
case `Escape`:
setActive(false);
break;
case ' ':
case 'SpaceBar':
case 'Enter':
e.preventDefault();
setSelectedThenCloseDropdown(index, filter, item);
break;
default:
break;
}
};
return (
<>
<div className={style.dropdownWrapper} id={id}>
{options.map((option) => {
return (
<div key={option.current.id + option.current.name} className={style.dropdownWrapper}>
<div className={style.dropdownContainer}>
<button
role="button"
onClick={handleActive}
aria-haspopup="listbox"
aria-expanded={active}
type="button"
className={style.dropdownToggle}>
{option.current.name}
</button>
{active && (
<div
role="listbox"
aria-activedescendant={option[selectedOption]}
tabIndex={-1}
className={style.dropdownMenu}>
{option.list.map((item, index) => {
/* istanbul ignore next */
return (
<a
role="option"
tabIndex={0}
onKeyDown={handleKeyDown(index, option, item)}
aria-selected={selectedOption == index}
className={style.dropdownItem}
key={item.name + option.current.name}
onClick={() => {
option.handler(item);
setActive(false);
setSelectedOption(index);
}}>
{item.name}
</a>
);
})}
</div>
)}
</div>
</div>
);
})}
</div>
</>
);
};
export default Dropdown;