首页 > 解决方案 > React 钩子 - 无法在输入字段中输入 [不重复]

问题描述

您可以在此处查看完整代码: CODESANDBOX LINK

这真的很奇怪。我有一个输入字段列表,这些字段根据按钮单击动态呈现

const newFields = (index) =>
<div>
    <input value={inputs[index].name}  onChange={e => handleNameInput(e,index)} />
    <input value={inputs[index].age} type="number" onChange={e => handleAgeInput(e,index)} />
    <Button onClick={() => setInputArray(inputArray => [...inputArray, newFields(++index)])}>Add</Button>
</div>

我正在尝试存储输入的值并在更改时更新它们。但正如标题中所述,我无法在输入字段中输入,一旦我单击一个字符,输入就会失去焦点。我不知道为什么会这样。

以下是状态和 handleInput 函数:

  let [inputs, setInputs] = useState(Array.apply(null, Array(100)).map(function () { return {
    name: '',
    age: ''
  } }));

const handleNameInput = (e, i) =>{
  let tempArr = new Array();
  tempArr = [...inputs];
  tempArr[i].name = e.target.value;
  setInputs([...tempArr]);
}

//handleAgeInput is exactly the same

标签: reactjsreact-hooks

解决方案


我认为您的主要问题是数组的重复使用。事实是,您只需要一组数据。因此,您需要围绕它构建组件。如果您在状态上创建另一个数组,则会增加复杂性,这会导致您成为当前问题。

了解为什么没有更新

你是onChange函数调用更新inputs数组状态。但是,你正在渲染inputArray他没有任何改变的地方。没有setInputArray调用,没有重新渲染。

提议

我了解您的需求有提案实施:

function App() {
  let [inputArray, setInputArray] = useState([{
    name: "",
    age: ""
  }]);

  const handleNameInput = useCallback(
    (e, i) => {
      inputArray[i].name = e.target.value;
      setInputArray([...inputArray]);
    },
    [inputArray]
  );

  const handleAgeInput = useCallback(
    (e, i) => {
      inputArray[i].age = e.target.value;
      setInputArray([...inputArray]);
    },
    [inputArray]
  );

  const handleNewField = useCallback(() =>
    setInputArray(inputArray => [...inputArray, {
      name: "",
      age: ""
    }]),
    []
  );

  return (
    <div className="App">
      {inputArray.map((element, i) => (
        <div>
          <input
            value={element.name}
            onChange={e => handleNameInput(e, i)}
          />
          <input
            value={element.age}
            type="number"
            onChange={e => handleAgeInput(e, i)}
          />
          <button
            onClick={handleNewField}>
            Add
          </button>
        </div>
      ))}
    </div>
  );
}

根据你的需要,也许你应该适应它。有一些方法可以避免重新渲染整个列表。但是这样你就可以编辑所有字段

另一种正确的方法是将每个字段分组为另一个 Component.with 独立状态。

如果您只想要按钮一次,请将他从循环中移开。

如果您只想显示最后设置的字段,请inputArrays[inputArray.length]全部使用而不是循环。

解释 :

您正在渲染一个组件数组,{ inputArray.map((e, i) => { return <div key={i}> {e} </div>; })}其中e应该是一个组件。

另一方面,您正在维护一个“隐藏”第一个数组的数据数组。

据我所知,你的用例的主要概念应该是直接从你的数据——你的数据数组中渲染你的组件。这样,您只有一个事实来源。


推荐阅读