#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, и он работал. Странно, что это не работает в моей местной среде