使用TRPC useQuery遇未处理运行时错误:钩子渲染数量不一致
解决“Rendered more hooks than during the previous render”错误
错误原因
你遇到的这个错误是违反了React Hooks核心规则导致的:所有Hooks必须在组件的顶层作用域调用,不能放在条件判断、循环或嵌套函数里。
初始渲染时路由参数id还未加载完成,你的代码会提前返回<LoadingSpinner />,此时根本没调用useQuery;当id加载完成后,组件会继续执行到useQuery的调用,导致两次渲染的Hooks数量不一致,直接触发报错——哪怕你设置了enabled: false也没用,因为问题出在Hook是否被调用,而非它是否执行查询。
最简单的解决方法
把useQuery移到组件顶层,通过enabled选项控制查询是否执行,同时保留对id的校验逻辑:
import type { NextPage } from "next"; import Image from "next/image"; import { useSession } from "next-auth/react"; import { useRouter } from "next/router"; import { api } from "@/utils/api"; import { LoadingSpinner } from "@/components/loading"; const EvaluationPage: NextPage = () => { const { data: session } = useSession(); const router = useRouter(); const { id } = router.query; // 将useQuery移至组件顶层,确保每次渲染都调用该Hook const { data } = api.image.getEvaluation.useQuery( { id: id as string, // 添加类型断言,后续会校验id合法性 }, { // 仅当id为有效非数组字符串时,启用查询 enabled: !!id && !Array.isArray(id), } ); // 原提前返回逻辑移至Hook调用之后 if (!id || Array.isArray(id)) { return <LoadingSpinner />; } return ( <> <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-br from-blue-400 to-indigo-800"> {session ? ( <div className="container flex flex-col items-center justify-center gap-12 px-4 py-12 "> <h1 className="font-base text-3xl tracking-tight text-gray-100 sm:text-3xl"> Image evaluation </h1> <>{data && <p className="text-white">{data.response}</p>}</> </div> ) : ( <div className="flex flex-col items-center justify-center gap-4 py-4"> <h3 className="text-center text-2xl text-gray-100"> Please sign in to continue. </h3> </div> )} </main> </> ); };
关键修改点说明
- Hook移至顶层:无论
id是否存在,每次渲染都会调用useQuery,保证Hooks调用数量始终一致,从根源解决报错。 - 动态控制查询启用:通过
enabled: !!id && !Array.isArray(id)实现仅当id有效时才触发查询,和你原本想通过enabled: false实现的效果一致。 - 保留加载状态:原提前返回逻辑调整位置后,不影响用户看到的加载效果,只是调整了执行顺序以符合Hooks规则。
内容的提问来源于stack exchange,提问作者peternovak
相关产品推荐
相关产品推荐

