在useSWR钩子中发生突变而不更新DOM



这是一个next.js应用程序,我使用useSWR钩子填充数据。

const { data, error } = useSWR('/api/digest', fetcher, {
revalidateOnFocus: false,
})

问题是,在下面的mutate()行之后,DOM没有按预期更新。但是,如果我将数据硬编码为updatedData,并将其作为mutate的arg传递,它将正常工作。事实是dataupdatedData是相同的。请参阅下面的评论。

编辑:如果我点击任何导航栏<Link/>,它会被更新。

有发生什么的线索吗?

const handleAddRowClick = async () => {
const newRow = { category: selectedCategory, entity: selectedEntity }
data.subscription[selectedCategory].push(selectedEntity);
console.log(data); // This data is equal to updatedData

const updatedData = {
"subscription": {
"materialFact": [
"Boeing"
],
"headlines": [
"thejournal",
"onemagazine" // ***This is the value added.
]
}
}
// mutate('/api/digest', data, false) // This does not works.
mutate('/api/digest', updatedData , false) // It works.
}

我假设您在handleAddRowClick中使用的data属性与您从useSWR中获得的属性相同。现在,如果在data中更新一些深度嵌套的对象,它不会更改数据引用。它仍然指向旧对象。因此,如果再次将其传递给mutate,对于mutate,对象仍然相同,因此不会触发重新渲染。

我建议您执行以下操作,从data派生updatedData,然后将其传递给mutate函数。

const handleAddRowClick = async () => {
const updatedData = {
...data,
subscription: {
...data.subscription,
[selectedCategory]: [
...data.subscription[selectedCategory],
selectedEntity,
]
}
}
mutate('/api/digest', updatedData , false);
}

顺便说一句,你也可以使用类似immer的东西来简化复制状态。