Home > other >  How can I change state of current map item in react component
How can I change state of current map item in react component

Time:05-16

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>

    )
  • Related