仅更新字符串数组时如何进行状态更新

How to make State update when only a string array is update

伙计们,我有下面这个示例代码:

const [data, setData] = useState([{question: '', option: ['']}]);

然后 datasetData 将传递到我的组件,如:

<Question setData={setData} data={data}/>

我在问题组件中的代码是:

const handleAddOption = (questionIndex: number) => {
    let newArray = data;

    newArray.map((item: any, i: number) => {
      if (i === questionIndex) {
        newArray[questionIndex].options.push('');
      }
    });

    setData(newArray);
  };

问题是,如果我添加一个新的整个对象,它会 "refresh" 我的页面并显示,但是,当我像最后几行代码一样添加时,数组中只有一个新字符串,它会不是 "re-render".

有人知道怎么解决吗?

  1. 你好像打错了 newArray[questionIndex].option.push(''); 而不是 newArray[questionIndex].options.push('');
  2. 但如果没有帮助,请尝试 forceUpdate(); 更多详细信息 您可以在这个答案中找到 or try to use this package https://github.com/CharlesStover/use-force-update

祝你好运:)

Rough implementation


我认为你可以改变:

const [data, setData] = useState([{question: '', option: ['']}]);

// into

const [questions, setQuestions] = useState([]);

当您收到新的问题对象时,您可以 setQuestions([...questions, newQuestion])

也就是说,假设您有一个正在接收新问题输入的表单。如果是这种情况,在表单的 onSubmit 函数中,您可以生成新的问题对象,然后执行 setQuestions([...questions, newQuestion]).

在 React 中,第一个经验法则是不要直接改变状态。它适用于 class-based 组件和 setState,它适用于 redux 的减速器,它也适用于 hook-based useState

你需要

setData((data) => data.map((item, index) => {
  if (index !== questionIndex) return item;
  return {
     ...item,
     options: [
        ...item.options,
        ''
     ]
  };
}));

这里有几项要强调:

  1. 以及 class-based 组件的 setState 可以提供更新程序函数的回调。我最好跳过这里的详细描述。可能建议看一下 and ReactJS docs。是的,这与钩子无关,但它使用相同的逻辑。

  2. 我们需要将旧数据与更改合并,以保持我们不想更改的属性仍然存在。这就是几乎不使用的所有扩展运算符。查看 article on handling arrays 的 React

  3. 状态
  4. 最后但并非最不重要的一点是,我们已经直接检查 return item 如果不是我们想要更新而不做任何更改。这使我们确保没有相关的子组件 re-render 具有实际上完全相同的数据。您可以通过搜索查询 "referential equality" 找到更多信息(这里是您可能会找到的 one of article)。

PS 强制更新比完全重写代码看起来更容易。但是直接改变状态通常会在以后以不同的 hard-to-reproduce 错误结束。

您可能还想更改组件层次结构和数据结构。所以没有组件需要遍历整个数组来更新单个嵌套 属性.