使用useRouter获取URL参数传入GraphQL SDK触发Hook调用错误
错误原因与解决方案
核心问题
你犯的关键错误是:getProductParam()在模块的顶级作用域被执行了,也就是在任何React函数组件的渲染流程之外调用了useRouter这个Hook。
React Hook的规则明确要求:Hook只能在以下两种场景调用:
- 函数组件的函数体内(渲染阶段)
- 自定义Hook内部(名字以
use开头的函数)
你的代码里,export const { getBulbs } = getSdk(getProductParam(), gqlClient);这行是模块顶级代码,在页面加载时就会执行getProductParam(),此时根本没有进入React组件的渲染上下文,自然违反了Hook规则,触发报错。
解决方案
方案1:在组件内动态获取参数并调用SDK
不要在模块顶级初始化带参数的SDK,而是把SDK的调用逻辑放到组件内部:
import { getSdk } from "./generated/graphql"; import { useRouter } from "next/router"; import { GraphQLClient } from 'graphql-request'; import { useEffect } from "react"; const gqlClient = new GraphQLClient("http://localhost:3000/api/graphql"); export default function ProductPage() { const router = useRouter(); const { productId } = router.query; const { getBulbs } = getSdk(gqlClient); // 当productId存在时调用接口 useEffect(() => { if (!productId) return; getBulbs({ productId }).then((data) => { // 处理返回的数据 console.log(data); }); }, [productId, getBulbs]); return <div>产品页面内容</div>; }
方案2:封装自定义Hook复用逻辑
如果多个组件需要用到这个带参数的SDK方法,可以封装成自定义Hook:
// sdk-hooks.js import { getSdk } from "./generated/graphql"; import { useRouter } from "next/router"; import { GraphQLClient } from 'graphql-request'; const gqlClient = new GraphQLClient("http://localhost:3000/api/graphql"); export function useBulbsSdk() { const router = useRouter(); const { productId } = router.query; const sdk = getSdk(gqlClient); // 封装自动传入productId的getBulbs方法 const getBulbs = async () => { if (!productId) throw new Error("productId 参数未获取到"); return sdk.getBulbs({ productId }); }; return { getBulbs }; }
然后在组件中使用:
// ProductPage.jsx import { useBulbsSdk } from './sdk-hooks'; import { useEffect } from "react"; export default function ProductPage() { const { getBulbs } = useBulbsSdk(); useEffect(() => { getBulbs().then((data) => { // 处理数据 console.log(data); }).catch((err) => { console.error(err); }); }, [getBulbs]); return <div>产品页面内容</div>; }
内容的提问来源于stack exchange,提问作者Neil Kelsey
相关产品推荐
相关产品推荐

