使用useEffect调用API后切换路由报错:TypeError: func.apply is not a function
问题分析与解决方案
这个问题我之前也碰到过,根源其实很简单——你把async直接传给了useEffect的回调函数!
为什么会报错?
React的useEffect钩子对回调函数的返回值有严格要求:它要么返回一个用于清理操作的函数,要么返回undefined。但async函数的返回值是一个Promise对象,当你点击Link跳转路由导致当前组件卸载时,React会尝试把这个Promise当作清理函数来调用,自然就会抛出TypeError: func.apply is not a function——毕竟Promise不是函数,没法执行apply方法。
你用dummy数据时没问题,大概率是因为你当时没给useEffect加async回调,或者同步操作下Promise立即resolved,但本质上这个写法的隐患一直存在。
修复方案
把useEffect的外层async去掉,保持内部的fetchData为async函数即可,同时建议加上错误处理和请求取消逻辑(避免组件卸载后请求完成触发状态更新警告):
useEffect(() => { // 创建AbortController用于取消请求 const abortController = new AbortController(); const fetchData = async () => { try { const result = await axios('http://192.168.1.17:8000/stacks', { signal: abortController.signal // 绑定取消信号 }); setDisplayPosts(result.data); setIsLoading(false); } catch (error) { // 忽略主动取消的错误 if (error.name !== 'AbortError') { console.error('加载Stack数据失败:', error); setIsLoading(false); } } }; fetchData(); // 组件卸载时取消请求 return () => abortController.abort(); }, []);
额外说明
这样修改后,useEffect的回调返回的是一个清理函数(取消请求的逻辑),完全符合React的要求,跳转路由时就不会再触发那个错误了。同时,添加错误处理也能让你在API请求失败时更优雅地处理状态,避免页面一直处于加载状态。
内容的提问来源于stack exchange,提问作者boostedd
相关产品推荐
相关产品推荐

