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

React类组件转Hooks时dispatch调用then报错及栈溢出问题咨询

报错原因与修复方案

报错1:Property 'then' does not exist on type '(dispatch: any) => Promise'.ts(2339)

  • 原因:useDispatch默认的TypeScript类型定义没有适配异步中间件(比如你用到的redux-thunk)的返回值规则,TS无法识别dispatch异步thunk action后会返回Promise实例,因此判定返回值上不存在then方法。类组件的mapDispatchToProps中传入的dispatch已经经过react-redux的类型适配,所以不会出现该报错。
  • 修复方法:
    1. 先在全局的Redux类型声明文件中定义适配thunk的Dispatch类型:
    // 通常写在redux/store.ts或者全局的类型文件中
    import { ThunkDispatch } from 'redux-thunk';
    import { RootState, AnyAction } from './你的类型定义路径';
    
    export type AppDispatch = ThunkDispatch<RootState, unknown, AnyAction>;
    
    1. 组件中使用自定义类型的useDispatch:
    const dispatch = useDispatch<AppDispatch>();
    
    如果你不想调整全局类型,也可以临时用类型断言解决:
    (dispatch(getFloorplan(currentSite.identif)) as Promise<void>).then(...)
    

报错2:Uncaught RangeError: Maximum call stack size exceeded at getFloorplan

  • 原因:你自定义的封装函数和从../redux/actions导入的异步action重名,导致调用时出现无限递归。你写的const getFloorplan = (site) => dispatch(getFloorplan(site))中,函数内部调用的getFloorplan不是你导入的action,而是你刚声明的当前变量,因此会无限调用自身触发栈溢出。

完整修复后的代码

import { useDispatch, useSelector } from 'react-redux';
// 导入的action保持原名,自定义封装函数换名避免冲突
import {
    getGraph,
    getFloorplan,
    changeActiveCamera,
} from "../redux/actions";
// 导入你定义的AppDispatch类型
import { AppDispatch } from '../redux/store';

const YourComponent = () => {
  const dispatch = useDispatch<AppDispatch>();
  const currentSite = useSelector((state) => state.selection.currentSite);
  const currentCamera = useSelector((state) => state.selection.currentCamera);
  // 别忘了你原来用到的realGraph也要从store中取
  const realGraph = useSelector((state) => state.realGraph);

  // 封装的函数换名避免和导入的action重名,也可以省略封装直接在loadGraph里写dispatch逻辑
  const dispatchGetFloorplan = (site) => dispatch(getFloorplan(site));
  const dispatchGetGraph = (site) => dispatch(getGraph(site));
  const dispatchChangeActiveCamera = (site, id) => dispatch(changeActiveCamera(site, id));
  
  const loadGraph = () => {
    if (currentSite) {
      dispatchGetFloorplan(currentSite.identif).then(() => {
        console.log("Fetched floorplan");

        dispatchGetGraph(currentSite.identif).then(() => {
          console.log("Fetched model", realGraph.model);

          if (currentCamera) {
            dispatchChangeActiveCamera(
              currentSite.identif,
              currentCamera.identif
            );
          }
        });
      });
    }
  };

  // 剩余组件逻辑...
}

如果你不需要单独封装dispatch方法,也可以直接在loadGraph中调用dispatch,代码更简洁:

const loadGraph = () => {
  if (currentSite) {
    dispatch(getFloorplan(currentSite.identif)).then(() => {
      console.log("Fetched floorplan");
      dispatch(getGraph(currentSite.identif)).then(() => {
        console.log("Fetched model", realGraph.model);
        if (currentCamera) {
          dispatch(changeActiveCamera(currentSite.identif, currentCamera.identif));
        }
      });
    });
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:48:00