【问题标题】:How to update, extend arrays by using useState in React -TypeScript?如何在 React -TypeScript 中使用 useState 更新、扩展数组?
【发布时间】:2021-01-05 15:59:01
【问题描述】:

请帮帮我。 我想动态添加额外的输入文件并将值保存到 textValues 状态。
这是我到目前为止所尝试的:

const [textValues, setTextValues] = useState([]);
const [numberOfTexts, setNumberOfTexts] = useState(5); <--- this value will be change dynamically
{[...Array(numberOfTexts)].map((x, i) => (
 <TextField
  style={{ marginLeft: "10px", marginTop: "10px" }}
  id="standard-basic"
  label="Text value"
  value={textValues[i]}
  onChange={(e: { target: { value: any } }) =>
  setTextValues(e.target.value)
}
/>
))}

因此,在这种情况下,我希望出现 5 个输入字段,并且在 textValues 数组中为 5 个空字符串,而不是逐步填写。我希望能够增加和减少 numberOfTexts,并根据文本数量更新所有内容。感谢您的帮助!

【问题讨论】:

  • 尝试将setTextValues(e.target.value)更新为setTextValues(numberOfTexts + 1)

标签: arrays reactjs typescript dynamically-generated use-state


【解决方案1】:

对于简单的用例,您不需要 2 个useState 来处理字段数量及其值。

通常这是定义最小数据集模型的最佳实践。

您可以在setTextValues 之上编写抽象函数,它应该可以解决问题;)

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [textValues, setTextValues] = useState([]);

  const addField = () => {
    setTextValues(textValues.concat([""]));
  };

  const updateField = (index, newValue) => {
    const newValues = textValues.map((val, idx) => {
      if (idx === index) {
        return newValue;
      }
      return val;
    });

    setTextValues(newValues);
  };

  const removeField = () => {
    setTextValues(textValues.slice(0, textValues.length - 1));
  };

  return (
    <div>
      <button onClick={() => addField()}>Add field</button>
      <button onClick={() => removeField()}>Remove (last) field</button>
      <br />
      <div>
        {textValues.map((textValue, idx) => (
          <input
            style={{ marginLeft: "10px", marginTop: "10px" }}
            id="standard-basic"
            label="Text value"
            value={textValue}
            onChange={(e) => {
              updateField(idx, e.target.value);
            }}
          />
        ))}
      </div>
    </div>
  );
}

更进一步,您可能希望创建自定义挂钩来抽象此逻辑,并拥有可重用的状态块。 API 可能如下所示:

const { addField, removeField, updateField } = useInputArray(['hello', 'yo'])

【讨论】:

  • 谢谢西蒙·布鲁诺。这是一个很好的解决方案。因为我使用打字稿,所以我只需要对代码进行一些更改。就像代替 const [textValues, setTextValues] = useState([]);我写了 const [textValues, setTextValues] = useState([] as string[]);
  • 不客气 ;) 要键入 useState,您必须更喜欢使用泛型:useState&lt;string[]&gt;([])
【解决方案2】:

到目前为止,不需要对代码进行太多更改的一种方法是使用useEffect() 挂钩在numberOfTexts 更改时更新字符串数组。

您可以通过添加以下代码来做到这一点:

useEffect(() => {
  let dif = numberOfTexts - textValues.length;
  if (dif > 0) {
    setTextValues(textValues.concat(Array(dif).fill('')));
  } else if (dif < 0) {
    setTextValues(textValues.slice(0, numberOfTexts));
  }
}, [numberOfTexts]);

这将根据numberOfTexts 数组动态更新textValues 数组。

【讨论】:

    猜你喜欢
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多