Как выбрать и отменить выбор в раскрывающемся списке react

#javascript #arrays #reactjs #select #deselect

Вопрос:

У меня есть выпадающий список. Пользователи могут выбрать несколько элементов из выпадающего списка. В то же время пользователи могут отменить выбор выбранных ими элементов, снова щелкнув по выбранным элементам. Если пользователи выберут «все», будут отображаться все числа в массиве.

Как это реализовать? Это то, что у меня есть до сих пор, введите описание ссылки здесь

 import "./styles.css";
import React, { useState } from "react";

const options = [1, 2, 3, 4, 5];

export default function App() {
  const [nums, setNum] = useState([]);

  const handleArrChange = ({ target }) => {
    setNum([...nums, target.value]);
  };
  return (
    <div className="App">
      <select
        onChange={handleArrChange}
        value={"select a number" || nums.length > 0}
      >
        <option disabled>select a number</option>
        {options.map((option) => (
          <option>{option}</option>
        ))}
      </select>
      {nums.map((num) => (
        <p>{num}</p>
      ))}
    </div>
  );
}
 

Ответ №1:

Это похоже на множественный селектор (пользовательская реализация выбора).

Пример:

 import React, { useState } from 'react';
import Select from 'react-select';
 
function App() {
  const data = [
    {
      value: 1,
      label: "cerulean"
    },
    {
      value: 2,
      label: "fuchsia rose"
    },
    {
      value: 3,
      label: "true red"
    },
    {
      value: 4,
      label: "aqua sky"
    },
    {
      value: 5,
      label: "tigerlily"
    },
    {
      value: 6,
      label: "blue turquoise"
    }
  ];
 
  // set value for default selection
  const [selectedValue, setSelectedValue] = useState([]);
 
  // handle onChange event of the dropdown
  const handleChange = (e) => {
    setSelectedValue(Array.isArray(e) ? e.map(x => x.value) : []);
  }
 
  return (
    <div className="App">
      <h3>Get selected by only value for multi select - <a href="https://www.cluemediator.com">Clue Mediator</a></h3>
 
      <Select
        className="dropdown"
        placeholder="Select Option"
        value={data.filter(obj => selectedValue.includes(obj.value))} // set selected values
        options={data} // set list of the data
        onChange={handleChange} // assign onChange function
        isMulti
        isClearable
      />
 
      {selectedValue amp;amp; <div style={{ marginTop: 20, lineHeight: '25px' }}>
        <div><b>Selected Value: </b> {JSON.stringify(selectedValue, null, 2)}</div>
      </div>}
    </div>
  );
}
 
export default App;
 

введите описание изображения здесь

Ссылка: https://www.cluemediator.com/how-to-get-selected-by-only-value-for-multi-select-in-react-select

Ответ №2:

Живой рабочий пример: https://react-3gte8y.stackblitz.io/

код : https://stackblitz.com/edit/react-3gte8y?file=src/App.js

Сначала сохраните массив параметров, содержащий только числа:

 const options = [1, 2, 3, 4, 5];
 

затем в вашей функции обработчика onChange проверьте, существует ли выбранное значение уже в состоянии nums, если его нет, добавьте его, иначе удалите его
, как это сделать? легко получить индекс значения с помощью indexOf метода, если он возвращает -1, это означает, что число не существует в num массиве, иначе indexOf вернет фактический индекс выбранного вами числа:

 const handleArrChange = ({ target }) => {

        setNum((prev) => {

          //get index of actual target.value
          const index = prev.indexOf(target.value);

          /*if index === -1 means not exist in array will return the prev 
          state and appending new chosen value*/
          if (index === -1) {

            return [...prev, target.value];

          }

           /* else (value exist) use splice to remove the chosen value from 
           the array */
          prev.splice(index, 1);

          /* don't use return prev, React will not detect changes in your 
          state and will not re render it */
          return [...prev];

        });
      };
 

prev-это предыдущее состояние, оно сохраняет фактическое состояние до внесения каких-либо изменений в состояние num.

Теперь внесите некоторые изменения в свой JSX, сначала не забудьте ключи и не забудьте установить значение выбора по умолчанию для select параметра отключено:

 <select onChange={handleArrChange} value={"select"}>
    <option disabled>select</option>
    {options.map((option) => (
        <option key={option}>{option}</option>
    ))}
</select>
 

и

 {nums.map((num) => (
        <p key={num}>{num}</p>
      ))}
 

Теперь вам нужно одно-выбрать Все и отменить выбор всех

сначала добавьте все в свои параметры:

 <select onChange={handleArrChange} value={"select"}>
        <option disabled>select</option>
        <option>All</option>
        {options.map((option) => (
          <option key={option}>{option}</option>
        ))}
</select>
 

затем в обработчике функции onChange проверьте, все ли проверено:

 if(target.value === "All"){
        if(nums.length > 0 ){
            setNum([])
        }else{
            setNum(options)
        }
        return
    }
 

этот код должен быть первым, что вы делаете, когда выбираете изменение значения, добавьте его в верхнюю часть своей функции onChange:

вот полный рабочий код:

 import React, { useState } from "react";

const options = [1, 2, 3, 4, 5];

export default function App() {


  const [nums, setNum] = useState([]);
  
  const handleArrChange = ({ target }) => {

    if(target.value === "All"){
        if(nums.length > 0 ){
            setNum([])
        }else{
            setNum(options)
        }
        return
    }

    setNum((prev) => {

      const index = prev.indexOf(target.value);

      if (index === -1) {

        return [...prev, target.value];

      }

      prev.splice(index, 1);

      

      return [...prev];
    });

  };
  return (
    <div className="App">

        <select onChange={handleArrChange} value={"select"}>

            <option disabled>select</option>

            <option>All</option>

            {options.map((option) => (

            <option key={option}>{option}</option>

            ))}

        </select>

        {nums.map((num) => (

            <p key={num}>{num}</p>

        ))}

    </div>

  );
}
 

Комментарии:

1. Привет @butalin! Спасибо за помощь! Я опробовал твое решение. Когда я переключу выбранный 1, 1 исчезнет из массива, но когда я выберу 2, 1 снова появится в массиве с 2

2. Да, я вижу это с помощью песочницы, но я попробовал тот же код на своем компьютере, и он хорошо работает, я думаю, это побочный эффект codesandbox.io, пожалуйста, попробуйте это в вашей местной среде

3. взгляните сюда stackblitz.com/edit/react-3gte8y?file=src/App.js

4. Привет @butalin! Я только что попробовал это и в своей местной среде! Это то же самое, что происходит в codesandbox.

5. Да! Я просмотрел ваш код в stackblitz, и он работал. Странно, что это не работает в моей местной среде