Home > OS >  Store multiple selected options in state
Store multiple selected options in state

Time:08-22

I'm creating a dropdown using list items in React and am mapping through the data to get each option displayed. I want the user to be able to select multiple options and for all selected options to be saved in the state.

Currently the last option they select is being saved in an array in the state but I cannot get all of their selected options to be saved in the state because they aren't able to select multiple so they are only stored in the previous state.

How can I store multiple selected list items in an array in the state?

 const [selectedSymptoms, setSelectedSymptoms] = useState(null)

                       const handleSymptoms = (symptom) => {
                       setSelectedSymptoms([symptom.Name])
                    // selectedSymptoms !== null && selectedSymptoms.push(symptom.Name)
                       console.log(selectedSymptoms)
                       }

                            <button
                            className={styles.selectSymptomBtn}
                            type="button"
                            onClick={toggleSymptoms}
                        >
                            Select your symptom
                        </button>

                        <ul className={`${isSymptomsOpen ? styles.show : styles.hide}`}>
                            {data.symptoms.map((symptom) => (
                                <li onClick={(() => handleSymptoms(symptom))}>
                                    {symptom.Name}
                                </li>))}</ul>

CodePudding user response:

The current logic is completely replacing the state value with an array of a single symptom name.

If you need to append, or remove, elements from the array then I suggest using a functional state update.

Example:

const [selectedSymptoms, setSelectedSymptoms] = useState([]);

...

const handleSymptoms = (symptom) => {
  setSelectedSymptoms(symptoms => {
    if (symptoms.includes(symptom.Name)) {
      // symptom name already selected, remove it
      return symptons.filter(name => name !== symptom.Name);
    } else {
      // symptom name non selected, add it
      return [...symptoms, symptom.Name];
    }
  });
};

CodePudding user response:

A Set would make the most sense here. This will prevent duplicates from being added if the user selects the same symptom twice, without having to search the entire array.

Passing a function to setSelectedSymptoms will give you access to the previous state.

const [selectedSymptoms, setSelectedSymptoms] = useState(new Set());

const handleSymptoms = (symptom) => setSelectedSymptoms((prev) => prev.add(symptom.Name));

Docs for Set: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set


You can expand this to easily deselect a symptom on a second click as well

  const handleSymptoms = (symptom) =>
    setSelectedSymptoms((prev) =>
      prev.delete(symptom.Name) ? prev : prev.add(symptom.Name)
    );
  • Related