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

自定义Hook中更新Redux State未触发组件重渲染问题排查

Redux自定义Hook状态不更新问题

我创建了一个Redux Slice,还写了自定义包装Hook(真的烦{ type: x, payload: y }这种语法 :p)。

以下是Slice代码:

// polycanvas.ts (Redux)

export const polycanvas = createSlice({
  name: 'polycanvas',
  initialState,
  reducers: {
    // Arcs
    addArc: (state, action: PayloadAction<Arc>) => {
      if (state.arcs.length < state.settings.arc.maxArcs) {
        state.arcs = [...state.arcs, action.payload];
      } else {
        throw(`Number of arcs exceeds the maximum. (max: ${state.settings.arc.maxArcs}, got: ${state.arcs.length})`);
      }
    },
    removeArc: (state, action: PayloadAction<number>) => {
      if (state.arcs[action.payload]) {
        state.arcs = state.arcs.filter((_, index) => index != action.payload);
      } else {
        throw(`Tried removing arc at index ${action.payload}. No such arc exists.`);
      }
    },
    setArcs: (state, action: PayloadAction<Arc[]>) => {
      if (action.payload.length < state.settings.arc.maxArcs) {
        state.arcs = action.payload;
      } else {
        throw(`Number of arcs exceeds the maximum. (max: ${state.settings.arc.maxArcs}, got: ${action.payload.length})`);
      }
    },

    //... other stuff
  }
});

export const usePolycanvas = () => {
  const dispatch = useAppDispatch();

  const arcs = useAppSelector(state => state.polycanvas.arcs);
  const arc = {
    addArc: (arc: Arc) =>
      dispatch(polycanvas.actions.addArc(arc)),
    removeArc: (index: number) =>
      dispatch(polycanvas.actions.removeArc(index)),
    setArcs: (arcs: Arc[]) =>
      dispatch(polycanvas.actions.setArcs(arcs)),
    
    //... other stuff
  }

  return { arc, arcs };
}

在我看来,这是Redux的正确用法。

在我的React组件中:

// Polycanvas.tsx (React Component)

export default () => {
  const { arc, arcs } = usePolycanvas();

  const makeArcs = (arcCount: number): void => {
    const _arcs = [];
    for (var i = 0; i < arcCount; i++) {
      const velocity = (4 * Math.PI * (settings.speed.loops - i)) / settings.speed.timeframeSeconds;
      _arcs.push({
        color: { r: 255, g: 255, b: 255, a: 0.3 },
        velocity,
        nextImpactTime: calculateImpactTime(startTime, velocity),
      });
    }
    arc.setArcs(_arcs);
  }


  React.useEffect(() => {
    makeArcs(10);
  }, []);

  React.useEffect(() => {
    console.log(arcs);
  }, [arcs]);

  return (<canvas ref={ref} className="polycanvas" />);
  // Ref is used for drawing to the canvas - not relevant in this example
}

控制台只打印[],除非修改文件触发Vite的HMR功能,否则组件不会实际渲染。我哪里操作错了吗?Redux不支持这种行为吗?

编辑:补充了可复现的代码示例。


问题排查与解决

问题出在setArcs reducer的条件判断逻辑上:

if (action.payload.length < state.settings.arc.maxArcs) {

你这里使用了小于的判断条件,但你尝试添加10个arcs,而state.settings.arc.maxArcs的值正好是10,此时10 < 10不成立,代码会直接抛出错误,不会执行state.arcs = action.payload,导致Redux状态里的arcs始终是初始的空数组[]。

同时addArc里的判断也存在同样的逻辑问题:当arcs数量等于最大值时,无法添加新的arc。

把两个判断条件改成小于等于即可解决问题:

// 修改addArc的判断
if (state.arcs.length <= state.settings.arc.maxArcs) {
  // ...
}

// 修改setArcs的判断
if (action.payload.length <= state.settings.arc.maxArcs) {
  // ...
}

另外,建议在dispatch action时添加错误捕获,避免因抛出错误导致后续代码终止执行:

const makeArcs = (arcCount: number): void => {
  // ... 生成_arcs的逻辑
  try {
    arc.setArcs(_arcs);
  } catch (err) {
    console.error('设置arcs失败:', err);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:53:08