#javascript #reactjs #react-hooks
Вопрос:
У меня есть число n, которое может быть любым значением, и я хочу отобразить n полей ввода, отслеживая состояние каждого ввода, но мне трудно понять, как это сделать. Например, если n = 3, я хочу сделать что-то вроде этого:
<div>
<input onChange={(e) => setValue1(e.target.value)}/>
<input onChange={(e) => setValue2(e.target.value)}/>
<input onChange={(e) => setValue3(e.target.value)}/>
< /div>
В этом примере мне нужно было бы вручную создать три состояния: value1, value2, value3. Моя цель-сделать его динамичным, поэтому, если в будущем я изменю n на 4 или любое другое число, мне не придется вручную создавать новые состояния и возиться с компонентом. Есть ли хороший способ сделать это с помощью крючков?
Ответ №1:
Вы должны создать состояние ввода, чтобы отслеживать каждый ввод:
import React, { useState } from 'react';
import './style.css';
export default function App() {
const [inputs, setInputs] = useState(Array(10).fill(''));
const inputChangedHandler = (e, index) => {
const inputsUpdated = inputs.map((input, i) => {
if (i === index) {
return e.target.value;
} else {
return input;
}
});
setInputs(inputsUpdated);
};
return (
<div>
{inputs.map((input, i) => (
<input onChange={e => inputChangedHandler(e, i)} value={input} />
))}
</div>
);
}
Вы можете проверить здесь, как все работает:
https://stackblitz.com/edit/react-sdzoqh
Ответ №2:
Вы можете создать новый массив с useState
крючком размера num
, который передается от его родителя, а затем использовать его индекс, т. Е. i
вы можете изменить его входное значение с помощью setValue
функции.
Просто для демонстрационной цели и заставьте input
перейти на новую строку, в которую я ее завернул div
.
export default function App({ num }) {
const [arr, setValue] = useState(Array(num).fill(""));
console.log(arr);
function onInputChange(index, event) {
console.log(event.target.value);
setValue((os) => {
const temp = [...os];
temp[index] = event.target.value;
return temp;
});
}
return (
<div className="App">
{arr.map((n, i) => {
return (
<div key={i}>
<input onChange={(e) => onInputChange(i, e)} value={n} />
</div>
);
})}
</div>
);
}
Ответ №3:
Может быть, я бы создал пользовательский крючок для создания своих входных данных, таких как
import React, { useState } from "react";
const CreateInput = (n) => {
const array = new Array(n).fill("");
const [valueInput, setValueInput] = useState({});
const handleChange = (event) => {
const { name, value } = event.target;
setValueInput({
...valueInput,
[name]: value,
});
};
const Input = array.map((_, i) => (
<input key={i} name={i} onChange={handleChange} />
));
return {
Input,
};
};
const Inputs = () => {
const { Input } = CreateInput(3);
console.log(Input);
return <div>{Input}</div>;
};
export default Inputs;
Ответ №4:
Это можно было бы сделать с массивом в состоянии, со значениями во входных данных. Инициализировать пустыми строками
const [values, setValues] = useState(Array(n).fill(""))
const handleChange = (e, i) => {
const copy = values;
copy[i] = e.target.value
setValues(copy)
}
return (
<div>
{Array(n).map((x,i) => (
<input value={values[i]} onChange={e => handleChange(e,i)} />
))}
</div>
)
Ответ №5:
вы можете использовать useState([]) с массивом в качестве значения по умолчанию, например
импорт «./styles.css»; импорт React, { useState } из «react»;
export default function App() {
const n = 3;
const [values, setValues] = useState(new Array(n).fill(1, 0, n));
const handleChange = (i, value) => {
const v = [...values];
v[i] = value;
setValues(v);
};
const inputsRendrer = (values) => {
return values.map((v, i) => {
return (
<input
key={i}
value={values[i]}
onChange={(event) => handleChange(i, event.target.value)}
/>
);
});
};
return <div className="App">{inputsRendrer(values)}</div>;
}
new Array(n).fill(1, 0, n) // this create new array with values of 1 and length of n`