我有下面的示例代码:
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);
};
问题是,如果我添加一个新的整个对象,它将“刷新”我的页面并显示,但是,当我像最后几行代码一样添加时,只有数组内的新字符串才不会“重新-呈现”。
有人知道如何解决这个问题吗?
答案 0 :(得分:0)
newArray[questionIndex].option.push('');
而不是newArray[questionIndex].options.push('');
forceUpdate();
的更多详细信息,您可以在此答案How can I force component to re-render with hooks in React?中找到,或尝试使用此软件包https://github.com/CharlesStover/use-force-update 祝你好运:)
答案 1 :(得分:0)
我认为您可以更改:
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,
''
]
};
}));
这里有几项要突出显示:
以及基于类的组件的setState
,都可以将回调函数提供给updater函数。我最好不要在这里详细描述它。可能建议看看SO question和ReactJS docs。是的,这与钩子无关,但是它使用相同的逻辑。
我们需要将旧数据与更改合并,以使我们不想更改的属性仍然存在。这就是所有这些散布运算符都很少使用的地方。看看article on handling arrays处于React的状态
最后但并非最不重要的一点是,我们检查是否直接返回item
,如果不是,我们希望不做任何更改就进行更新。这可以确保没有相关的子组件将使用实际完全相同的数据重新渲染。您可以通过搜索查询“参照相等”来找到其他信息(这里是one of article,您可以找到。)
PS强制更新而不是完全重写代码可能看起来容易得多。但是直接直接改变状态通常会在以后导致不同的难以重现的错误。
此外,您可能想更改组件层次结构和数据结构。因此,不需要任何组件就可以遍历整个数组来更新单个嵌套属性。