react Bug:即使数组作为依赖变量没有改变,useEffect也会被触发,

1cosmwyk  于 8个月前  发布在  React
关注(0)|答案(4)|浏览(100)

React版本:所有

重现步骤

  1. 声明一个状态变量,类型为数组,例如:useState([1, 2, 3]);
  2. 在依赖数组中添加一个包含声明的状态变量的useEffect。
  3. 使用相同的值更新状态变量。
    这种情况可能发生是因为,如果在设置状态值后使用'=='检查状态值,那么对于数组的比较总是返回false,从而触发useEffect。
  1. [1, 2, 3] == [1, 2, 3] is false:
  2. "This condition will always return 'false' since JavaScript compares objects by reference, not value."

链接到代码示例:

  1. const [arrVar, setArrVar] = useState([]);
  2. useEffect(() => {
  3. console.log("triggered");
  4. console.log(arrVar);
  5. }, [arrVar])
  6. //Click the button twice.
  7. return (
  8. <button onClick={ (e) => {setArrVar([1, 2, 3])} }>update state</button>
  9. );

当前行为

即使在更新时依赖数组中的数组元素没有改变,useEffect也会被触发。

预期行为

它不应该被触发。

pes8fvy9

pes8fvy91#

这是预期的行为。React遍历旧的和新的依赖数组,并进行“浅等”比较。换句话说,if (oldDeps[i] !== newDeps[i]) runCallback()

你提供了一个新的数组引用,并将其包含在依赖数组中。因此,你改变了deps数组的内容,所以它会运行effect回调。这并不重要那个数组的内容是否相同或不同——重要的是deps数组内部的值和引用。

py49o6xq

py49o6xq2#

这个条件将始终返回'false',因为JavaScript是通过引用而不是值来比较对象的。
你已经回答了自己。如果比较返回false,无论数组是否包含相同的数据,都应该重新渲染组件,因为在依赖数组中找到的值不相等。

yxyvkwin

yxyvkwin3#

感谢你的回复。我看到这是预期的行为,它的表现方式符合我的猜测。但这是期望的行为吗?难道useEffect的依赖数组不是用来检测变化并执行一些代码的吗?在这一点上,我认为每次在设置新的状态数据为数组之前,我需要做的就是使用for循环将其与之前的值进行比较。这个操作对我来说没有问题。但是想象一下,每个React用户都在他们的代码中使用这个比较函数。这对“React”来说不是一个期望的状态吗?如果useEffect的依赖数组比较函数通过JavaScript的for循环或其他方式检查引用而不是值的数组和其他对象,而不是使用“===”,那么整体上会更干净的代码吗?或者更新设置状态函数,我指的是useState()返回的第二个元素,如果值相同,则不更新状态?这只会在那些想要保持相同值但改变引用的人身上出现问题,如果有的话。

omqzjyyz

omqzjyyz4#

如果要在上面的例子中不触发 useEffect ,需要将依赖数组指定为 arrVar ,而不是 [arrVar] 。否则,您会比较数组(从此渲染器获取的 arrVar 与从先前渲染器获取的 arrVar ),这将始终是 false ,从而触发 useEffect
arrVar 作为依赖数组传递将使 React 比较 arrVar 的内容。
或者执行 [...arrVar] 。这也可以工作,但请不要在实际代码中这样做,谢谢 :)

相关问题