How do I convert the below code so that if I call
<div><Example/></div>
<div><Example/></div>
<div><Example/></div>
When I click on one Example item and then click on another one the previously opened Example
item closes? Currently, the item will only close when it is clicked on and will stay open if I click on another.
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button
onClick={() => setOpen(!open)}
aria-controls="example-collapse-text"
aria-expanded={open}
className="Collapse-Test"
data-open={open}
>
click
</Button>
<Collapse in={open}>
<div id="example-collapse-text">
Hidden Text
</div>
</Collapse>
</>
);
};
CodePudding user response:
Lift the state up to the parent component so it can control what is currently selected and toggled open. Update the Example
component to take open
and onClick
props.
Example component
interface IExample {
open: boolean;
onClick: () => void;
}
function Example({ open, onClick }: IExample) {
return (
<>
<Button
onClick={onClick}
aria-controls="example-collapse-text"
aria-expanded={open}
className="Collapse-Test"
data-open={open}
>
click
</Button>
<Collapse in={open}>
<div id="example-collapse-text">
Hidden Text
</div>
</Collapse>
</>
);
};
Parent component
const [openId, setOpenId] = useState<number | null>(null);
const toggleHandler = (id: number) => () => {
// toggle closed if already open, otherwise set new open id
setOpenId(openId => openId === id ? null : id);
};
...
<div>
<Example open={openId === 1} onClick={toggleHandler(1)} />
</div>
<div>
<Example open={openId === 2} onClick={toggleHandler(2)} />
</div>
<div>
<Example open={openId === 3} onClick={toggleHandler(3)} />
</div>