【问题标题】:Add and Remove input component on click of a Button in ReactJS在 ReactJS 中单击按钮时添加和删除输入组件
【发布时间】:2021-11-23 10:06:35
【问题描述】:

我试图实现一个带有输入框的表单,允许用户在单击按钮时添加/删除文本输入组件,这是我目前所拥有的,

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 函数是否有任何问题。另外,我在不同的文件中声明了 handleChange 函数。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    你必须删除最后一个元素,所以先试试这个发送最后一个索引号,

    textInput.splice(0, -1);
    

    这样就可以了,

     const removeInput = () => {
           const textInput = [...textBox];
           textInput.splice(0, -1);
           setTextBox(textInput);
     };
    

    【讨论】:

    • 我试过那样做,但没用
    【解决方案2】:

    您的代码存在一些问题,但导致您出现问题的问题是在对数组进行切片时。

    拼接问题

    removeInput() 中,您接受index 参数,但是当您将处理程序提供给onClick 时,您没有给它一个索引。这意味着 index 是该处理程序 (docs on React events) 的事件对象,它不是数字。在这种情况下,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 文档中的 documentation for lists and keys

    在渲染输入时这可能是个问题,因为在 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>      
      )
     }
    

    希望对您有所帮助,如果您还有其他问题,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      相关资源
      最近更新 更多