You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useState设置相同数组值时为何仍触发组件重渲染?

问题根源

React对useState的更新判断用的是浅比较——只看值的内存引用是否一致。你两次调用setOrder传的数组内容完全一样,但它们是两个独立的数组实例(内存地址不一样),所以React会觉得状态变了,触发组件重渲染。

解决办法

给你几种实用的处理方式:

1. 先深比较再更新状态

调用setOrder前,先对比新数组和当前order的内容,只有真的不一样时才更新:

const newOrder = [500, 400, 400, 450];
// 用JSON.stringify做深比较,适合纯基础类型数组
const isSame = JSON.stringify(newOrder) === JSON.stringify(order);
if (!isSame) {
  setOrder(newOrder);
}

如果数组里有对象、函数这类复杂类型,JSON.stringify就不好使了,得自己写递归比较逻辑,或者用lodash的isEqual(注意控制依赖体积)

2. 用useEffect精准控制API调用

如果API调用是跟着状态更新走的,把它放进useEffect,用深比较后的结果当依赖:

useEffect(() => {
  // 这里写你的API调用逻辑
  callApi(order);
}, [JSON.stringify(order)]); // 只有数组内容变了,才执行API调用

也可以自己写个深比较的Effect钩子:

import { useEffect, useRef } from 'react';

function useDeepCompareEffect(callback, deps) {
  const prevDepsRef = useRef();
  if (!_.isEqual(prevDepsRef.current, deps)) {
    prevDepsRef.current = deps;
  }
  useEffect(callback, [prevDepsRef.current]);
}

// 用的时候这样写
useDeepCompareEffect(() => {
  callApi(order);
}, [order]);

3. 缓存数组引用

如果这个数组是固定不变的,用useMemo缓存它的引用,这样每次传的都是同一个数组:

const cachedOrder = useMemo(() => [500, 400, 400, 450], []);

// 之后调用setOrder就传这个缓存的变量
setOrder(cachedOrder);
setOrder(cachedOrder); // 两次引用相同,React不会触发重渲染

4. 函数式更新里做比较

用setOrder的函数式写法,对比当前状态和新状态的内容,相同就返回原状态:

setOrder(prev => {
  const newOrder = [500, 400, 400, 450];
  const isSame = JSON.stringify(prev) === JSON.stringify(newOrder);
  return isSame ? prev : newOrder;
});

这种情况如果内容一致,返回的是原状态的引用,React会直接跳过重渲染。

额外说明

你说别人视频里没这个问题,大概率是他们的场景里,两次setState传的是同一个引用的数组(比如提前缓存好的变量),或者状态是数字、字符串这类基础类型——基础类型的浅比较就是比值,相同值自然不会触发重渲染。

内容的提问来源于stack exchange,提问作者wynnawinner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:42:19