繁体   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