ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

wagmi `useConnection` Hook 完全指南:实时读取与订阅当前钱包连接状态

wagmi `useConnection` Hook 完全指南:实时读取与订阅当前钱包连接状态 wagmiuseConnectionHook 完全指南实时读取与订阅当前钱包连接状态【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmiuseConnection是 wagmi React 包中用于获取当前连接状态的核心 Hook它封装了wagmi/core的getConnection与watchConnection能力让组件能够以响应式方式读取地址、链、连接器等实时信息。本文基于仓库中 useConnection.md 文档并结合 useConnection.ts 源码、核心层 getConnection.ts 与 watchConnection.ts 实现以及对应测试带你掌握该 Hook 的参数、返回值、类型收窄技巧与底层运行原理。核心作用与适用场景useConnection返回一个描述当前连接的对象包含当前连接的账户地址address/addresses当前连接的链与链 IDchain/chainId当前使用的连接器connector例如 MetaMask、Coinbase Wallet 等连接生命周期状态status及其派生布尔标志isConnected、isConnecting、isReconnecting、isDisconnected。典型的适用场景包括根据连接状态切换 UI“连接钱包”按钮 / “账户信息”面板、展示当前账户地址与所在链、在交易前校验连接器与网络等。它是useConnect、useDisconnect等变更类 Hook 之外读取侧最常用的状态来源。导入与基础用法导入import { useConnection } from wagmi最简用法import { useConnection } from wagmi function App() { const connection useConnection() }在真实项目中通常配合WagmiProvider一起使用。Provider 通过 React Context 向下注入 Config使useConnection无需显式传参即可拿到配置import { WagmiProvider } from wagmi import { QueryClient, QueryClientProvider } from tanstack/react-query import { config } from ./config const queryClient new QueryClient() function App() { return ( WagmiProvider config{config} QueryClientProvider client{queryClient} YourApp / /QueryClientProvider /WagmiProvider ) }其中config由 config.ts 创建示例配置了主网与 Sepolia 两条链import { createConfig, http } from wagmi import { mainnet, sepolia } from wagmi/chains export const config createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, })注意useConnection的响应式更新依赖WagmiProvider或显式传入config参数。在没有 Provider 包裹的情况下直接调用会抛出WagmiProviderNotFoundError——该行为在 useConfig.ts 中实现。完整实践示例import { useConnection } from wagmi import { mainnet } from wagmi/chains function Account() { const { address, chain, connector, status } useConnection() if (status connected address) { return ( div p地址{address}/p p网络{chain?.name}/p p连接器{connector?.name}/p /div ) } if (status connecting || status reconnecting) { return p正在连接…/p } return p未连接/p }参数Parametersimport { type UseConnectionParameters } from wagmiUseConnectionParameters本质上是ConfigParameterconfig只有一个可选字段config类型Config | undefined作用显式指定要使用的 Config默认不传时从最近的WagmiProvider中获取。当组件树中不方便使用 Context例如在 Provider 之外的工具函数组件、或同一页面存在多个 Config 实例时可以显式传入import { useConnection } from wagmi import { config } from ./config function App() { const connection useConnection({ config, // 显式指定 Config }) }传入方式与useConfig保持一致useConfig内部采用parameters.config ?? useContext(WagmiContext)的取值策略见 useConfig.ts因此显式config的优先级高于 Context。返回值Return Typeimport { type UseConnectionReturnType } from wagmiUseConnectionReturnTypeconfig与wagmi/core的GetConnectionReturnTypeconfig完全一致见 useConnection.ts完整字段说明收录于 getConnection-return-type.md具体如下addressAddress | undefined来自连接器的已连接地址默认取addresses数组中的第一个地址。addressesreadonly Address[] | undefined来自连接器的已连接地址列表。chainChain | undefined来自连接器的已连接链。如果该链未在 config 中配置则为undefined即便连接器实际连在该链上。这一点与chainId的取值逻辑不同详见下文源码解析。chainIdnumber | undefined来自连接器的已连接链 ID。connectorConnector | undefined当前已连接的连接器如 MetaMask、Coinbase Wallet、WalletConnect 等。isConnecting / isReconnecting / isConnected / isDisconnectedboolean由status派生的四个布尔标志用于简化条件判断。statusconnecting | reconnecting | connected | disconnectedconnecting正在尝试建立连接reconnecting正在尝试与一个或多个连接器重新建立连接例如页面刷新后通过reconnectOnMount自动重连见 WagmiProvider.mdconnected至少有一个连接器已连接disconnected未与任何连接器建立连接。利用status收窄返回类型GetConnectionReturnType被定义为一个可辨识联合discriminated unionstatus就是判别字段见 getConnection.ts 中四个分支的类型定义。因此可以直接通过status做类型收窄让 TypeScript 帮你保证字段可用性。当status connected时address等属性被保证已定义import { type GetConnectionReturnType } from wagmi/core const connection {} as GetConnectionReturnType if (connection.status connected) { connection.address // Address非 undefined connection.chainId // number非 undefined }当status disconnected时address等属性被保证为undefinedif (connection.status disconnected) { connection.address // undefined connection.connector // undefined }这一收窄行为在 useConnection.test-d.ts 中有完整的类型测试四个status分支分别对应一组精确的字段类型约束例如connected分支要求address: Address、chainId: number、connector: Connector而disconnected分支要求全部为undefined。源码级原理一次 Hook 调用背后发生了什么从 React Hook 到 core Action 的调用链useConnection.ts 的实现非常精简核心只有三步export function useConnectionconfig extends Config ResolvedRegister[config]( parameters: UseConnectionParametersconfig {}, ): UseConnectionReturnTypeconfig { const config useConfig(parameters) return useSyncExternalStoreWithTracked( (onChange) watchConnection(config, { onChange }), () getConnection(config), ) }useConfig(parameters)解析出实际生效的 Config显式参数优先否则取 Context订阅subscribe调用watchConnection(config, { onChange })在连接状态变化时触发更新读取快照getSnapshot调用getConnection(config)计算当前连接快照并通过useSyncExternalStoreWithTracked接入 React 的并发安全外部存储机制。getConnection状态如何被组装核心实现位于 getConnection.ts。它从 Config 的内部状态中读取三类数据const uid config.state.current! // 当前连接器实例的 uid const connection config.state.connections.get(uid) // 连接记录accounts、chainId、connector const status config.state.status // 全局连接状态然后根据status的四个取值分别组装返回对象connectedaddress、addresses、chainId、connector均为非空值reconnecting字段可能已恢复address存在时isConnected为trueisReconnecting: trueconnectingisConnecting: true其余字段按当前部分数据返回disconnected所有账户、链、连接器字段统一为undefined。值得注意的实现细节是chain的取值const chain config.chains.find( (chain) chain.id connection?.chainId, )它通过chainId在config 已配置的链列表中查找这解释了为什么“连接器连到一条未在 config 中配置的链时chain会返回undefined而chainId仍能返回连接器上报的原始数值”。watchConnection变化如何被感知watchConnection.ts 负责订阅并提供了一个关键的相等性判断return config.subscribe(() getConnection(config), onChange, { equalityFn(a, b) { const { connector: aConnector, ...aRest } a const { connector: bConnector, ...bRest } b return ( deepEqual(aRest, bRest) aConnector?.id bConnector?.id aConnector?.uid bConnector?.uid ) }, })连接器对象connector本身可能是引用不稳定的实例因此单独用iduid比较其余字段使用deepEqual做深比较避免因对象引用变化而触发无意义的重新渲染。useSyncExternalStoreWithTracked按需订阅的细粒度优化useSyncExternalStoreWithTracked.ts 是对 React 官方useSyncExternalStore的增强封装它通过Object.defineProperties给返回对象注入带“记录访问 key”功能的 getter当组件只读取了status、address等部分字段时trackedKeys会记录这些 key后续状态变化时isEqual只比较被访问过的 key从而跳过无关字段变化引发的重渲染。这意味着一个只读取status的组件不会因为address的变化而重新渲染一个只读取address的组件也不会因为链切换而重渲染。这是 wagmi Hook 在大型应用中保持高性能的关键机制。与 core 层getConnection的关系useConnection本质上是 core 层 getConnection 的 React 响应式封装。core 层用法为命令式调用import { getConnection } from wagmi/core import { config } from ./config const connection getConnection(config)而 Hook 版额外提供了订阅与按需渲染能力两者返回值类型完全一致均指向GetConnectionReturnType。测试验证仓库中的测试覆盖了useConnection的核心行为useConnection.test.tstest(default, async () { const { result, rerender } await renderHook(() useConnection()) expect(result.current.address).not.toBeDefined() expect(result.current.status).toEqual(disconnected) await connect(config, { connector: config.connectors[0]! }) rerender() expect(result.current.address).toBeDefined() expect(result.current.status).toEqual(connected) await disconnect(config) })测试验证了两个关键点初始状态为disconnectedaddress未定义调用connect后Hook自动响应式更新为connectedaddress变为已定义disconnect后恢复。此外parameters: config用例验证了显式传入config的用法——该场景下组件不必被WagmiProvider包裹测试中使用React.Fragment作为 wrapper印证了config参数与 Context 互为替代的关系。常见实战模式1. 根据状态渲染登录 / 登出 UIfunction ConnectButton() { const { status, address } useConnection() if (status connected) return button{address}/button if (status connecting || status reconnecting) return button disabled连接中…/button return button连接钱包/button }2. 校验当前网络是否为目标链import { useConnection } from wagmi import { mainnet } from wagmi/chains function NetworkGuard() { const { chainId, status } useConnection() const isConnected status connected if (isConnected chainId ! mainnet.id) { return p请切换到主网后再进行操作/p } return null }3. SSR 场景注意WagmiProvider的reconnectOnMount默认为true见 WagmiProvider.md服务端渲染时首次快照通常为disconnected状态客户端水合后才可能自动重连并更新为connected。若需要服务端预填充状态可结合initialState使用避免首屏出现“未连接”闪动。小结useConnection以极薄的封装为 React 组件提供了完整、响应式、类型安全的连接状态读取能力唯一可选参数config让你可以在 Context 之外显式指定 Config返回值通过status判别联合实现精确的类型收窄connected状态下address、chainId、connector均被保证存在底层由getConnection状态组装watchConnection订阅与相等性判断useSyncExternalStoreWithTracked按需渲染优化三层协作兼顾正确性与性能与 core 层getConnection共享同一返回类型可在命令式与响应式两种风格间平滑切换。相关源码与文档Hook 实现 useConnection.ts、core Action getConnection.ts 与 watchConnection.ts、返回类型说明 getConnection-return-type.md、行为测试 useConnection.test.ts 与类型测试 useConnection.test-d.ts。【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表