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

调用useDispatch会触发组件强制重渲染吗?Immer场景下的疑问

问题解答

1. Immer对数组push操作的实际处理

你对Immer写时复制的理解存在偏差:当你对draft.products执行push操作时,Immer会创建新的数组实例。

原数组是不可变的,Immer的draft允许你以“可变”的方式编写逻辑,但背后会生成全新的不可变结构。对于数组的push、pop、splice这类会改变原数组的操作,Immer都会复制原数组并生成新数组,因此state.products的引用会发生变化。这也是为什么ComponentB的useSelector能检测到状态变化,触发重渲染——因为前后两次返回的数组引用不同,严格相等===检查不通过。

2. ComponentA重渲染的原因

useDispatch()本身不会触发组件重渲染,你的情况排除选项a,实际是ComponentA的重渲染源于React的默认渲染机制:

  • 如果ComponentA的父组件因为Redux store更新(或其他原因)发生重渲染,那么作为子组件的ComponentA会默认跟着重渲染(除非用React.memo包裹ComponentA,跳过不必要的重渲染)。
  • 你提到“若Immer创建了新数组,ComponentA不应重渲染”的想法是错误的:ComponentB的重渲染不会导致父组件ComponentA重渲染,但父组件的重渲染会传递给子组件。

补充:你的reducer写法修正

注意你当前的reducer写法存在问题:

// 错误写法
const reducer = produce((draft = initialData, action) => {
  // ...
});

// 正确写法:将初始状态作为produce的第二个参数
const reducer = produce((draft, action) => {
  switch (action.type) {
    case "Add":
      draft.products.push(action.payload);
      break;
    default:
      break;
  }
}, initialData);

这样才能确保初始状态被正确设置,避免潜在的状态异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:14:50