Web3Modal WalletConnect切换页面时连接状态丢失问题求助
问题分析
该问题源于Next.js客户端路由跳转时,Wagmi的钱包连接状态未自动同步,加上组件 hydration 逻辑与状态监听不完整,导致Web3Button无法感知钱包实际连接状态,出现连接后仍显示"Connect Wallet"、重复连接报错的情况。
修复方案
1. 优化Wagmi客户端初始化与路由监听
修改_app.js,添加路由切换监听,确保路由跳转后重新触发Wagmi连接检查,并将Web3Modal移至WagmiConfig上下文内:
import "../styles/globals.css"; import { ThemeProvider } from "next-themes"; import Layout from "../components/layout"; import { Provider } from "react-redux"; import { store } from "../redux/store"; import { Web3Modal } from "@web3modal/react"; import Meta from "../components/Meta"; import UserContext from "../components/UserContext"; import { useEffect, useRef, useState } from "react"; import { useRouter } from "next/router"; import { EthereumClient, w3mConnectors, w3mProvider, } from "@web3modal/ethereum"; import { configureChains, createClient, WagmiConfig } from "wagmi"; import { arbitrum } from "wagmi/chains"; function MyApp({ Component, pageProps }) { const [ready, setReady] = useState(false); const scrollRef = useRef({ scrollPos: 0, }); const router = useRouter(); const chains = [arbitrum]; const projectId = "xxxxxxxxxxxxxxxxxxxxxxxxxx"; const { provider } = configureChains(chains, [w3mProvider({ projectId })]); const wagmiClient = createClient({ autoConnect: true, connectors: w3mConnectors({ projectId, version: 2, chains }), provider, }); const ethereumClient = new EthereumClient(wagmiClient, chains); useEffect(() => { // 路由切换时重新触发连接检查 const handleRouteChange = () => { wagmiClient.connect({ connector: wagmiClient.connectors[0], reconnect: true }); }; router.events.on('routeChangeComplete', handleRouteChange); setReady(true); return () => { router.events.off('routeChangeComplete', handleRouteChange); }; }, [router, wagmiClient]); return ( <> {ready ? ( <WagmiConfig client={wagmiClient}> <Provider store={store}> <ThemeProvider enableSystem={true} attribute="class"> <UserContext.Provider value={{ scrollRef: scrollRef }}> <Layout> <Component {...pageProps} /> </Layout> </UserContext.Provider> </ThemeProvider> </Provider> {/* 将Web3Modal移入WagmiConfig上下文,确保状态同步 */} <Web3Modal themeVariables={{ "--w3m-accent-color": "#8358FF", "--w3m-background-color": "#131740", }} projectId={projectId} ethereumClient={ethereumClient} /> </WagmiConfig> ) : null} </> ); }
2. 强化Header组件的状态监听
修改Header组件,添加路由切换时的手动状态检查,确保组件能及时响应连接状态变化:
import Image from "next/image"; import Link from "next/link"; import DarkMode from "../mode/DarkMode"; import Logo from "./../../public/images/logo.png"; import WhiteLogo from "./../../public/images/logo_white.png"; import { v4 as uuidv4 } from "uuid"; import { useRouter } from "next/router"; import { isChildrenPageActive, isParentPageActive, } from "../../utils/daynamicNavigation"; import { useEffect, useState } from "react"; import { useAccount, useEnsName, useConnect } from "wagmi"; import { Web3Button } from "@web3modal/react"; import DropDownInfos from "./fragments/DropDownInfos"; export default function Header() { const { address, isConnected, isConnecting } = useAccount(); const { data: ensName } = useEnsName({ address }); const { connect } = useConnect(); const [toggle, setToggle] = useState(false); const [isCollapse, setCollapse] = useState(null); const [hydrated, setHydrated] = useState(false); const router = useRouter(); useEffect(() => { setHydrated(true); // 窗口resize处理 const handleResize = () => { if (window.innerWidth >= 1024) { setToggle(false); } }; window.addEventListener("resize", handleResize); // 路由切换时手动检查钱包状态 const handleRouteChange = () => { if (typeof window !== "undefined" && window.ethereum) { window.ethereum.request({ method: 'eth_accounts' }).then(accounts => { if (accounts.length > 0 && !isConnected) { connect({ connector: window.ethereum }); } }); } }; router.events.on('routeChangeComplete', handleRouteChange); return () => { window.removeEventListener("resize", handleResize); router.events.off('routeChangeComplete', handleRouteChange); }; }, [router, isConnected, connect]); /* Some code */ <div className="ml-8 hidden items-center lg:flex xl:ml-12"> {/* 根据连接状态动态显示按钮文本 */} <Web3Button label={isConnected ? "Disconnect" : "Connect"} icon="show" disabled={isConnecting} />
关键修复点说明
- 将Web3Modal移入WagmiConfig内部,确保组件能正确获取Wagmi上下文状态
- 路由切换时触发Wagmi重新连接检查,强制同步账户状态
- 在Header组件中添加路由监听,手动检查钱包账户,弥补自动同步的不足
- 以
isConnected、isConnecting作为依赖项,确保组件在状态变化时及时重渲染
额外建议
- 升级Wagmi与Web3Modal至最新版本,避免旧版本的路由同步bug
- 确保WagmiConfig在hydration完成后再渲染,避免状态初始化异常
内容的提问来源于stack exchange,提问作者Akamura Shumkurru
相关产品推荐
相关产品推荐

