Есть несколько инпутов range, для них одно состояние, как изменять каждый отдельно?
Есть несколько инпутов range, для них одно состояние, как изменять value каждого отдельно? Когда я перетаскиваю один из них, то изменяются все. Приложение работает логично, и это поведение понятно. Но как можно сделать, чтобы отдельно изменять каждый? .
Я перебирал с map информацию которая мне приходит с запроса, и как это реализовать никак не получается.
import React, { useEffect, useState } from "react";
import axios from 'axios';
const DonateList = () => {
const [donateList, setDonateList] = useState([]);
const [rangePrice, setRangePrice] = useState(0);
const rangeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRangePrice(parseInt(e.target.value));
}
return (
<>
{donateList.map((post: any, index: number) => (
<div className="donate__item" key={index}>
<img src="http://localhost:3000/static/media/02.d091f12c6b2a8040aabb.webp" alt="" className="donate-item__img" />
<div className="donate-item__content">
<div className="donate-item__title">{post.title}</div>
<div className="donate-item__description">{post.description}</div>
<div className="donate-item__range-content">
<input type="range" min={0} max={post.price} className='donate-item__range' onChange={rangeChange} value={rangePrice} />
<span className="donate-item__price">{rangePrice}/{post.price}</span>
</div>
</div>
</div>
))}
</>
)
}
export default DonateList;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Ответы (3 шт):
Не хватает пока репутации писать комментарии, поэтому напишу в ответе. :)
Если для всех нужно иметь один стейт, значит единственный выход - хранить в стейте массив объектов типа {key: xxx, value: yyy}. key брать тот который присваиваешь в map (у тебя это index).
При обновлении стейта не забудь обновлять через создание! нового объекта, а не изменение свойства объекта, т.е. нужно обновлять, используя спрэд-оператор.
Простой способ был SwaD'а.
Vasily, если будет возможность, то напишите пожалуйста пример кода, как оно должно выглядеть
Апдейт по просьбе @brutal Brutal, код не идеальный. Можно короче. Но код работает и демонстрирует идею.
import React, { useEffect, useState } from 'react';
import './App.css';
interface IInput {
key: string,
label: string,
value: string
}
const inputs: IInput[] = [
{
key: '1',
label: 'label 1',
value: ''
},
{
key: '2',
label: 'label 2',
value: ''
}
]
function App() {
const [state, setState] = useState<IInput[]>(inputs);
useEffect(() => {
console.log('state from useEffect', state)
}, [state])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
const inputIndex = Number(e.target.id);
const modifiedInput = {
...state[inputIndex],
value: e.target.value
}
const stateArray = [...state];
stateArray.splice(inputIndex, 1, modifiedInput);
setState([...stateArray]);
}
return (
<>
<div style={{ 'display': 'flex', 'flexDirection': 'column', 'width': '250px' }}>
{
inputs.map((input, index) => {
return (
<div key={index} style={{ 'display': 'flex' }}>
<label htmlFor={`${input.key}`}>{input.label}</label>
<input
id={index as unknown as string}
onChange={handleChange}
value={state[index]?.value}
/>
</div>
)
})
}
</div>
<div style={{ 'display': 'flex', 'flexDirection': 'column' }}>
<h2>State values</h2>
<span>{`0: ${state[0]?.value}`}</span>
<span>{`1: ${state[1]?.value}`}</span>
</div>
</>
);
}
export default App;
