自定义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
相关产品推荐
相关产品推荐

