簡體   English   中英

單擊 ReactJS 中的按鈕時添加和刪除輸入組件

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM