I have three dropdowns rendered on each map iteration. How can I change the state of each one of them independently?
Right now I can close current dropdown only when set state to new value by clicking on another dropdown
const [opened, setOpened] = useState(null);
const inputs = [{
id: 1,
title: "Location",
value: ["Berlin"]
},
{
id: 2,
title: "Date",
value: ["Sunday"]
},
{
id: 3,
title: "Time",
value: ["2am"]
}];
<div className="myDropdownButton">
{inputs.map((input, index) => (
<div className="myButtonWrapper">
<div onClick={() => handleClickedDropdown(index)}
placeholder={input.value}
className="myButton">
<div className="myButtonInner">
<div>
<label htmlFor="input" className="myLabel">{input.title}</label>
<input placeholder={input.value}
value={input.value}
className="myInput"
type="text"
readOnly/>
</div>
<span>▼</span>
</div>
</div>
<div className={opened === index ? "myDropdown" : "dropHidden"}>
<div className="myDropdownInnerWrapper">
<div className="myDropdownInner">
<div className="myLocationOptions">{input.id}</div>
<div className="myLocationOptions">{input.id}</div>
</div>
</div>
</div>
</div>
))}
</div>```
CodePudding user response:
You can check with index, I would create object state instead of string. Here is the working version https://codesandbox.io/embed/wonderful-wind-jiwvdi?fontsize=14&hidenavigation=1&theme=dark
import { useState } from "react";
import "./styles.css";
export default function App() {
const [opened, setOpened] = useState({ index: null, open: false });
const inputs = [
{
id: 1,
title: "Location",
value: ["Berlin"]
},
{
id: 2,
title: "Date",
value: ["Sunday"]
},
{
id: 3,
title: "Time",
value: ["2am"]
}
];
const handleClickedDropdown = (index) => {
if (index === opened.index) {
setOpened({ index: null, open: false });
} else {
setOpened({ index: index, open: true });
}
};
return (
<div className="myDropdownButton">
{inputs.map((input, index) => (
<div className="myButtonWrapper">
<div
onClick={() => handleClickedDropdown(index)}
placeholder={input.value}
className="myButton"
>
<div className="myButtonInner">
<div>
<label htmlFor="input" className="myLabel">
{input.title}
</label>
<input
placeholder={input.value}
value={input.value}
className="myInput"
type="text"
readOnly
/>
</div>
<span>▼</span>
</div>
</div>
<div className={opened.index === index ? "myDropdown" : "dropHidden"}>
<div className="myDropdownInnerWrapper">
<div className="myDropdownInner">
<div className="myLocationOptions">{input.id}</div>
<div className="myLocationOptions">{input.id}</div>
</div>
</div>
</div>
</div>
))}
</div>
);
}
CodePudding user response:
Set value of opened state toggled index of each element in map, then make a condition base on value of opened state to appear or hidden when it change. I think you try this below:
const [opened, setOpened] = useState(null);
const inputs = [{
id: 1,
title: "Location",
value: ["Berlin"]
},
{
id: 2,
title: "Date",
value: ["Sunday"]
},
{
id: 3,
title: "Time",
value: ["2am"]
}];
const handleClickedDropdown = (index) => {
setOpened(index)
}
return (
<div className="myDropdownButton">
{inputs.map((input, index) => (
<div className="myButtonWrapper">
<div onClick={() => handleClickedDropdown(index)}
placeholder={input.value}
className="myButton">
<div className="myButtonInner">
<div>
<label htmlFor="input" className="myLabel">{input.title}</label>
<input placeholder={input.value}
value={input.value}
className="myInput"
type="text"
readOnly />
</div>
<span>▼</span>
</div>
</div>
<div className="" style={{display: `${opened === index ? 'block' : 'none'}`}}>
<div className="myDropdownInnerWrapper">
<div className="myDropdownInner">
<div className="myLocationOptions">{input.id}</div>
<div className="myLocationOptions">{input.value}</div>
</div>
</div>
</div>
</div>
))}
</div>
)