[英]Add and Remove input component on click of a Button in ReactJS
我试图实现一个带有输入框的表单,该输入框允许用户在单击按钮时添加/删除文本输入组件,这是我到目前为止所拥有的,
const UserInput = () => {
const selectValues = ['Value 1', 'Value 2'];
const [textBox, setTextBox] = useState(selectValues);
const addNewTextInput = () => {
const newTextValue = 'Value' + textBox.length;
setTextBox([...textBox, newTextValue])
};
const removeInput = (index: number) => {
const textInput = [...textBox];
textInput.splice(index, 1);
setTextBox(textInput);
};
return (
<div>
<button onClick={addInput}>+</button>
<button onClick={removeInput}>+</button>
{textBox.map((value, i) => {
return (
<input
onChange={handleChange}
value={value}
id={i}
type={type}
/>
);
</div>
})}
)
}
现在,我可以添加新的文本输入并成功删除输入,但是当我删除时,不是最近添加的输入,而是第一个输入字段被删除。 我不确定 removeInput function 是否有任何问题。 另外,我在不同的文件中声明了 handleChange function。
你必须删除最后一个元素,所以先试试这个发送最后一个索引号,
textInput.splice(0, -1);
这样它就可以工作,
const removeInput = () => {
const textInput = [...textBox];
textInput.splice(0, -1);
setTextBox(textInput);
};
您的代码存在一些问题,但导致您出现问题的问题是在对数组进行切片时。
在removeInput()
中,您接受一个index
参数,但是当您将处理程序提供给onClick
时,您没有给它一个索引。 这意味着index
是该处理程序的事件 object ( 有关 React 事件的文档),它不是一个数字。 在这种情况下, splice()
调用默认删除第一个元素。 您需要执行以下操作:
const removeInput = () => {
// This is the proper way to change state that depends on previous state.
setTextBox((prevTextBox) => {
const mutatableTextBox = [...prevTextBox];
mutatableTextBox.splice(mutatableTextBox.length-1, 1);
return mutatableTextBox;
})}
key
问题在您的示例中,您还在不传递key
属性的情况下呈现项目列表。 React 在后台使用此属性来帮助它有效地呈现组件列表。 当你不提供key
属性时,React 默认使用索引 (i)。 这是 React 文档中列表和键的文档。
当你渲染你的输入时,这可能是一个问题,因为在 React 的眼中索引并没有改变。 请参阅以下示例以进行说明。
{["a", "b", "c"].map((letter) => <p>{letter}</p>)}
// React renders
<p>a</p>
<p>b</p>
<p>c</p>
// Change state and remove the value at index 1 (b)
{["a", "c"].map((letter) => <p>{letter}</p>)}
// React will now render:
<p>a</p>
<p>b</p>
为什么? 索引没有改变。 React 自动给 'a' 段落的索引为 0,'b' 有 1,'c' 有 2。当我们更改数组时,React 看到我们仍然有索引 0 和 1,所以它认为我们仍在使用'a' 和 'b',但我们不是。 我希望你能看到这可能是一个问题。
从技术上讲,这对您的代码无关紧要,因为您总是删除最后一个索引,但最好的做法是这样做:
const UserInput = () => {
// Math.random() is okay for this purpose, but a better alternative would
// be to use custom keys which are 100% guaranteed to be unique.
const selectValues = [
{text: "Value 1", key: Math.random()},
{text: "Value 2", key: Math.random()}
];
const [textBox, setTextBox] = useState(selectValues);
const addNewTextInput = () => {
setTextBox((prevTextBox) => {
const newTextValue = 'Value' + prevTextBox.length;
return [...prevTextBox, {text: newTextValue, key: Math.random()}];
});
};
const removeInput = () => {
// This is the proper way to change state that depends on previous state.
setTextBox((prevTextBox) => {
const mutatableTextBox = [...prevTextBox];
mutatableTextBox.splice(mutatableTextBox.length-1, 1);
return mutatableTextBox;
})}
return (
<div>
<button onClick={addInput}>+</button>
<button onClick={removeInput}>+</button>
{textBox.map((value, i) => {
return (
<input
onChange={handleChange}
value={value.text}
key={value.key}
id={i}
type={type}
/>
);
})}
</div>
)
}
我希望这会有所帮助,如果您还有其他问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.