0

I am trying to create a component called SelectMultiple.

import React, { useState } from "react";

const SelectMultiple = () => {
  const [skills, setSkills] = useState([]);

  const handleChange = event => {
    const { value } = event.target;

    const indexOfValue = skills.indexOf(value);

    if (indexOfValue === -1) {
      setSkills([...skills, value]);
    } else {
      setSkills(skills.filter(skill => skill !== value));
    }
  };

  return (
    <select multiple={true} value={skills} onChange={handleChange}>
      <option value="HTML">HTML</option>
      <option value="CSS">CSS</option>
      <option value="JavaScript">JavaScript</option>
    </select>
  );
};

export default SelectMultiple;

When I run this code, click HTML, HTML is selected, click HTML again, obviously, it does not unselect because onChange event has not fired.

What is the best way to get around this? Should I use a ref instead? What is the best practice for this kind of multi-select component?

New contributor
hugojavadi is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • Is there a reason you want to spin up your own code? react-select already supports this out of the box: github.com/JedWatson/react-select – Kyle Nov 8 at 18:31
  • @Kyle I'm a minimalist. Thanks for sharing react-select I will take a look. – hugojavadi Nov 8 at 18:49
1

You can access the selected items through event.target.selectedOptions.

function SelectMultiple () {
  const [skills, setSkills] = useState([]);

  const handleChange = event => {

    var selectedSkills = Array.from(event.target.selectedOptions, (item) => item.value)

    setSkills(selectedSkills);
  };

  return (
    <>
    <select multiple={true} value={skills} onChange={handleChange}>
      <option value="HTML">HTML</option>
      <option value="CSS">CSS</option>
      <option value="JavaScript">JavaScript</option>
    </select>
    <hr />
     Selected Skills{JSON.stringify(skills)}
    </>
  );
}

Codesandbox:

http://codesandbox.io/s/select-multiple-5w0tw

  • Thank you for answering. Your component will only allow the user to select one skill. – hugojavadi Nov 9 at 13:49
  • No, you can select multiple items with Ctrl – SuleymanSah Nov 9 at 13:50
  • @hugojavadi you can try it works like this: const [skills, setSkills] = useState(["CSS","JavaScript"]); or just use Ctrl key in keyboard – SuleymanSah Nov 9 at 13:51
  • @hugojavadi you can read the Selecting multiple options in this link: developer.mozilla.org/en-US/docs/Web/HTML/Element/select this is the way how we choose multiple options. – SuleymanSah Nov 9 at 14:11
  • Ah, I stand corrected! Thank you, @SuleymanSah. – hugojavadi Nov 10 at 14:05
-1

Maybe I'm not understanding the question correctly, but you should be able to change the onChange to onClick. Does that do what you want?


const SelectMultiple = () => {
  const [skills, setSkills] = useState([]);
  console.log("hit");
  const handleChange = event => {
    const { value } = event.target;
    const indexOfValue = skills.indexOf(value);
    console.log(indexOfValue, value);
    if (indexOfValue === -1) {
      setSkills([...skills, value]);
    } else {
      setSkills(skills.filter(skill => skill !== value));
    }
  };
  console.log(skills);

  return (
    <select multiple={true} value={skills} onClick={handleChange}>
      <option value="HTML">HTML</option>
      <option value="CSS">CSS</option>
      <option value="JavaScript">JavaScript</option>
    </select>
  );
};

export default SelectMultiple;

Your Answer

hugojavadi is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.