React+TypeScript调用serviceCall报not a function错误如何解决
问题原因定位
1. 首要原因:Context 未正确包裹组件
你创建 ApiContext 时设置的默认值是空对象{},如果使用useUsers钩子的组件没有被<APIProvider>嵌套在内部,那么useApi()拿到的就是默认空对象,不存在serviceCall方法,就会抛出你遇到的serviceCall is not a function类型错误。
排查验证:检查调用useUsers的组件所在的父组件/路由结构,必须满足如下嵌套规则:
// 根组件示例结构 import { APIProvider } from "./providers/API"; import { GoogleAuthProvider } from "./providers/authentication"; function App() { return ( <GoogleAuthProvider> <APIProvider> {/* 所有用到useApi、useGoogleAuth、useUsers的组件/路由都要放在这个层级内 */} <AppRoutes /> </APIProvider> </GoogleAuthProvider> ) }
2. 次要问题:serviceCall 调用方式和定义不匹配
就算Context包裹正确,当前的调用写法也会报错:你定义的serviceCall要求传入一个包含endpoint、method、tokenId属性的对象(符合IServiceCallProps接口),但你现在调用时传的是三个分散的参数,参数格式不匹配。
修复方案
- 先按照上面的嵌套规则确认所有用到对应钩子的组件都在
APIProvider的包裹范围内。 - 修改
useUsers里的serviceCall调用方式,改为传入对象参数:
const signInUser = (tokenId: string) => { serviceCall({ endpoint: "/users/signin", method: "GET", tokenId: tokenId }) .then(() => console.log("User signed in")) .catch(() => { signOut(); setTokenId(); }); };
- (可选TS优化)给Context加上明确类型定义,避免后续出现同类隐式问题,还能在开发阶段快速定位未被Provider包裹的错误:
// 在APIProvider文件内提前定义Context类型 interface IApiContext { serviceCall: (props: IServiceCallProps) => Promise<any>; setTokenId: React.Dispatch<React.SetStateAction<string | undefined>>; tokenId: string | undefined; } // 创建Context时指定类型,默认值加错误提示 const ApiContext = React.createContext<IApiContext>({ serviceCall: () => { throw new Error("useApi必须在APIProvider内部使用") }, setTokenId: () => {}, tokenId: undefined });
内容的提问来源于stack exchange,提问作者Martin Fuentes
相关产品推荐
相关产品推荐

