React类组件转Hooks遇ts(2339)错误及回调内realGraph值为undefined问题
问题原因及解决思路
1. dispatch调用then时报错的问题
你当前使用的是redux-thunk异步方案,类组件版本无报错是因为connect高阶组件在封装mapDispatchToProps时,已经默认适配了thunk的返回值类型,dispatch异步action后会直接返回Promise实例,因此可以正常调用then方法。
而Hooks版本的useDispatch默认返回的Dispatch类型仅支持普通同步action,没有包含thunk的类型定义,因此TS检测不到返回值为Promise,就抛出了类型错误。
解决方法
给useDispatch指定适配thunk的类型即可,示例代码:
// 可以先把通用类型定义放到redux全局类型文件里 import { ThunkDispatch } from 'redux-thunk'; import { AnyAction } from 'redux'; // 此处RootState替换为你自己项目的全局redux状态类型 type AppDispatch = ThunkDispatch<RootState, unknown, AnyAction>; // 组件内使用时指定类型 const dispatch = useDispatch<AppDispatch>();
临时调试也可以用类型断言绕开校验:
(dispatchGetFloorplan(currentSite.identif) as unknown as Promise<void>).then(...)
2. loadGraph内realGraph.model输出undefined的问题
这是典型的Hooks闭包陷阱问题,原因如下:
- 类组件中通过
this.props取值,this.props本身是可变对象,异步回调执行时取到的永远是最新的props值,因此可以正常输出。 - 函数组件的
loadGraph函数在创建时,会捕获当前渲染周期的realGraph值,等到异步请求完成执行then回调时,用到的还是当初捕获的旧realGraph(此时store里的realGraph虽然已经更新,但闭包内的引用还是初始值),所以输出undefined。把console语句移到函数外后,每次组件重新渲染都会执行该语句,自然能拿到更新后的值。
解决方法
可任选以下一种方案:
- 如果你的thunk异步action已经把接口返回结果return了,直接在
then回调里取返回值即可,不需要从store读取:
dispatchGetGraph(currentSite.identif).then((res) => { console.log('Fetched model', res.model); })
- 用
useRef存储最新的realGraph值,每次更新就同步到ref中,回调里从ref取值:
const realGraph = useSelector((state) => state.graphArticles.graph); const realGraphRef = useRef(realGraph); useEffect(() => { realGraphRef.current = realGraph; }, [realGraph]); // 回调内读取ref的current属性 console.log('Fetched model', realGraphRef.current.model);
- 用
useCallback包裹loadGraph,把realGraph加入依赖数组,保证每次realGraph更新都会生成新的loadGraph,捕获最新值。
内容的提问来源于stack exchange,提问作者user10727450
相关产品推荐
相关产品推荐

