将状态设置为 useEffect
内的原始值工作正常,而将其设置为数组/对象会导致我无法理解的多次渲染。我想知道是什么依赖导致它多次渲染。你能解释一下吗?
import React, { useEffect, useState } from 'react'
export const UseEffectSetStateError = () => {
const [arr, setArr] = useState([1, 2, 3]);
useEffect(() => {
setArr([4, 5, 6]) // this gives error
// setArr(0) // commenting above line and uncommenting this works fine
}, [arr])
return (
<div>
</div>
)
}
答案 0 :(得分:3)
当你这样做
setArr(0)
新的 arr
状态是 ===
到状态中的先前值(在第一个效果挂钩运行之后)。 React 检测到这一点并在所有新状态值 ===
到旧状态值时跳过重新渲染,因此不会发生进一步的渲染,因此不会再次调用效果回调。
相反,运行
setArr([4, 5, 6])
总是将 new 数组放入状态。每次效果挂钩运行时,您都在创建一个全新的数组并将其放入状态。
console.log([1, 2] === [1, 2]);
它们不是 ===
,所以 React 会重新渲染,导致无限循环。
只是为了好奇,如果你这样做了
const someArr = [4, 5, 6];
export const UseEffectSetStateError = () => {
// ..
useEffect(() => {
setArr(someArr);
不会有重新渲染循环,因为在这里,新的集合数组是旧集合数组的===
; someArr === someArr
状态,因此在第二次运行效果回调后将跳过重新渲染。
答案 1 :(得分:1)
添加到 CertainPerformance 的答案中,您为什么要使用“arr”作为依赖项。从它的外观来看,您不是在每次 arr 的值发生变化时都试图触发该函数,对吗?您需要定义一个状态变量来告诉您的 useEffect 运行。如果你能更好地解释你的用例,我可以提供一个具体的例子。但我会说使用类似的东西:
const [triggerUseEffect, setTriggerUseEffect] = useState(0)
useEffect(() => {
setArr([4,5,6])
}, [triggerUseEffect])
在应该触发 useEffect 的函数内,添加这一行:
setTriggerUseEffect(p => p+1);