我正在尝试在功能组件内创建一个react上下文提供程序。我正在使用useState挂钩为其他组件提供数组,并具有将新值推送到数组的add函数。数组和add函数都通过上下文提供程序提供。
似乎是通过将push与状态挂钩一起使用
var newArray = array
newArray.push("text")
setArray(newArray)
不会导致使用状态的组件重新呈现,但是在使用时
setArray(array=> [...array, "text"])
使用通过上下文提供程序提供的数组的组件会进行更新。
任何人都可以解释为什么会这样吗?
答案 0 :(得分:1)
数组在javascript中是可变的,因此当您创建变量并将其指向数组时(如您的示例)
var newArray = array
newArray实际上并不复制其实例,而是仅存储对其的引用。您可以在下面的浏览器控制台中完成的一个非常简单的示例中看到这一点
在示例中通过推入新变量来对数组进行变异时,它将仅将其添加到初始阵列中,对状态进行变异并且不会导致重新渲染。在将setArray调用到新数组后,React协调时,它会看到该数组(引用)是相同的,并且不会导致重新渲染。
在使用扩展符号示例时,您将通过使用[]
创建一个新数组,只需为new Array
使用语法糖,然后将旧条目中的项目清空到新条目中。在将旧状态与新状态及其新项目进行比较时,React看到了差异并重新提供了组件。
但是,如果您希望按照最初设置的方式进行操作,则可以使用.slice()数组函数,以便使用要调用的数组中存在的数据创建一个新数组,这样它将是var newArray = array.slice()
。如果将项目添加到新数组并设置状态,它将重新呈现。
答案 1 :(得分:0)
使用扩展运算符...
设置状态时,您正在创建新对象。如果您没有使用它,并且您正在使用旧对象React
设置状态,则不会更新您的组件,因为state属性不会更改(对对象的引用也不会更改)。就像我一开始所说的那样,您实际上是在使用[... array]
创建新对象(新引用),因此React更新了状态。
答案 2 :(得分:0)
了解状态突变。
在反应中,您必须先不改变状态才能重新渲染。如果将对象推入数组中,那是突变,它不会为该状态变量创建新的引用,并且react无法确定它是否已更新。 React使用浅表比较,因此即使数组的内容不同,引用也是相同的。您需要更新参考以触发渲染。