React挂钩-无法在输入字段中输入[不可重复]

时间:2020-05-07 10:35:05

标签: reactjs react-hooks

您可以在此处查看完整的代码: 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>

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

以下是状态和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

1 个答案:

答案 0 :(得分:0)

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

了解为什么没有更新

您正在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。

如果您希望按钮一次滚动,请将其从循环中移出。

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

说明:

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

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

据我所知,用例的主要概念应该是直接从数据(即数据数组)中渲染组件。 这样,您只有一个真理来源。