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

时间:2019-06-28 20:27:14

标签: reactjs react-hooks

我有下面的示例代码:

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

然后 data setData 将传递给我的组件,例如:

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

我在Question组件中的代码是:

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

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

    setData(newArray);
  };

问题是,如果我添加一个新的整个对象,它将“刷新”我的页面并显示,但是,当我像最后几行代码一样添加时,只有数组内的新字符串才不会“重新-呈现”。

有人知道如何解决这个问题吗?

3 个答案:

答案 0 :(得分:0)

  1. 您似乎输入了newArray[questionIndex].option.push('');而不是newArray[questionIndex].options.push('');
  2. 但是,如果仍不能解决问题,请尝试forceUpdate();的更多详细信息,您可以在此答案How can I force component to re-render with hooks in React?中找到,或尝试使用此软件包https://github.com/CharlesStover/use-force-update

祝你好运:)

答案 1 :(得分:0)

Rough implementation


我认为您可以更改:

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

// into

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

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

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

答案 2 :(得分:0)

在反应中,第一个经验法则是不要直接改变状态。它适用于基于类的组件和setState,适用于redux的化简器,也适用于基于钩子的useState

您需要

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

这里有几项要突出显示:

  1. 以及基于类的组件的setState,都可以将回调函数提供给updater函数。我最好不要在这里详细描述它。可能建议看看SO questionReactJS docs。是的,这与钩子无关,但是它使用相同的逻辑。

  2. 我们需要将旧数据与更改合并,以使我们不想更改的属性仍然存在。这就是所有这些散布运算符都很少使用的地方。看看article on handling arrays处于React的状态

  3. 最后但并非最不重要的一点是,我们检查是否直接返回item,如果不是,我们希望不做任何更改就进行更新。这可以确保没有相关的子组件将使用实际完全相同的数据重新渲染。您可以通过搜索查询“参照相等”来找到其他信息(这里是one of article,您可以找到。)

PS强制更新而不是完全重写代码可能看起来容易得多。但是直接直接改变状态通常会在以后导致不同的难以重现的错误。

此外,您可能想更改组件层次结构和数据结构。因此,不需要任何组件就可以遍历整个数组来更新单个嵌套属性。