[英]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.