For simple usecase you don't need to have 2 useState
to handle the number of fields and their values.
Usually this is a best practice to define the minimal data set model.
You can write abstract function on top of setTextValues
, it should do the trick ;)
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [textValues, setTextValues] = useState([]);
const addField = () => {
setTextValues(textValues.concat([""]));
};
const updateField = (index, newValue) => {
const newValues = textValues.map((val, idx) => {
if (idx === index) {
return newValue;
}
return val;
});
setTextValues(newValues);
};
const removeField = () => {
setTextValues(textValues.slice(0, textValues.length - 1));
};
return (
<div>
<button onClick={() => addField()}>Add field</button>
<button onClick={() => removeField()}>Remove (last) field</button>
<br />
<div>
{textValues.map((textValue, idx) => (
<input
style={{ marginLeft: "10px", marginTop: "10px" }}
id="standard-basic"
label="Text value"
value={textValue}
onChange={(e) => {
updateField(idx, e.target.value);
}}
/>
))}
</div>
</div>
);
}
To go further, you may want to create custom hook to abstract this logic, and have reusable chunk of state. The API may look like this:
const { addField, removeField, updateField } = useInputArray(['hello', 'yo'])
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…