Next.js中使用Wagmi的usePrepareContractWrite等Hook报错:无QueryClient
解决Next.js中Wagmi usePrepareContractWrite/useContractWrite报错"No QueryClient set"的问题
在Next.js路由组件中使用Wagmi连接智能合约时,useAccount()可以正常运行,但调用usePrepareContractWrite()或useContractWrite()时出现以下错误:
error Error: No QueryClient set, use QueryClientProvider to set one
报错位置:at Mint (./src/app/mint/page.js:39:87)
用户相关代码:
"use client"; import { wagmiConfig } from "../wagmi"; import {WagmiConfig,useAccount,usePrepareContractWrite, useContractWrite} from "wagmi"; import { abi } from "./abi"; import { useState, useEffect} from "react"; export default function Mint() { const [expectedAmount, setExpectedAmount] = useState(0); const { address, isConnected } = useAccount(); const { config } = usePrepareContractWrite({ abi: abi, address: "0xe058C0881aC0BF32743b091623708b7FDe75636e", functionName: "mint", args: [500], }); useEffect(() => { setExpectedAmount(amount - (amount * 1) / 100); }, [amount]); const body = () => { if (isConnected) { return ( // some frontend ui ); } }; return ( <WagmiConfig config={wagmiConfig}> //some frontend ui </WagmiConfig> ); }
问题原因
核心问题出在组件层级和hooks执行顺序上:
你在Mint组件的顶层直接调用了usePrepareContractWrite,但WagmiConfig是在该组件的return语句中才渲染的。React hooks的调用逻辑是在组件渲染前执行,此时WagmiConfig还未挂载,而usePrepareContractWrite依赖Wagmi内部集成的React Query QueryClient,因此会触发找不到QueryClient的错误。
而useAccount属于Wagmi的基础账户状态钩子,不依赖React Query,所以能正常工作。
解决方案
方案1:将WagmiConfig提升到根布局(推荐)
把WagmiConfig放到app/layout.js中,让所有路由组件都能共享Wagmi配置和QueryClient:
修改app/layout.js:
"use client"; import { WagmiConfig } from "wagmi"; import { wagmiConfig } from "./wagmi"; export default function RootLayout({ children }) { return ( <html lang="en"> <body> <WagmiConfig config={wagmiConfig}> {children} </WagmiConfig> </body> </html> ); }
然后修改Mint组件,移除内部的WagmiConfig:
"use client"; import {useAccount,usePrepareContractWrite, useContractWrite} from "wagmi"; import { abi } from "./abi"; import { useState, useEffect} from "react"; export default function Mint() { const [expectedAmount, setExpectedAmount] = useState(0); const [amount, setAmount] = useState(0); // 补充原代码中缺失的amount状态 const { address, isConnected } = useAccount(); const { config } = usePrepareContractWrite({ abi: abi, address: "0xe058C0881aC0BF32743b091623708b7FDe75636e", functionName: "mint", args: [500], }); useEffect(() => { setExpectedAmount(amount - (amount * 1) / 100); }, [amount]); const body = () => { if (isConnected) { return ( // some frontend ui ); } }; return ( <div>{body()}</div> ); }
方案2:拆分组件,将hooks调用放在WagmiConfig内部
如果不想修改根布局,可以把使用合约钩子的逻辑拆成子组件,放在WagmiConfig内部:
修改Mint组件:
"use client"; import { wagmiConfig } from "../wagmi"; import {WagmiConfig,useAccount,usePrepareContractWrite, useContractWrite} from "wagmi"; import { abi } from "./abi"; import { useState, useEffect} from "react"; // 子组件:内部调用需要QueryClient的hooks const MintContent = () => { const [expectedAmount, setExpectedAmount] = useState(0); const [amount, setAmount] = useState(0); const { address, isConnected } = useAccount(); const { config } = usePrepareContractWrite({ abi: abi, address: "0xe058C0881aC0BF32743b091623708b7FDe75636e", functionName: "mint", args: [500], }); useEffect(() => { setExpectedAmount(amount - (amount * 1) / 100); }, [amount]); if (isConnected) { return ( // some frontend ui ); } return <div>请连接钱包</div>; }; export default function Mint() { return ( <WagmiConfig config={wagmiConfig}> <MintContent /> </WagmiConfig> ); }
内容的提问来源于stack exchange,提问作者Tam2006
相关产品推荐
相关产品推荐

