wagmi @wagmi/solid useDisconnect 原语完全指南:在 Solid.js 应用中安全断开钱包连接
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
useDisconnect是@wagmi/solid包提供的 mutation 类原语(primitive),用于在 Solid.js 应用中主动断开当前(或指定)连接器与钱包的连接。本文基于官方文档 useDisconnect 说明 展开,并结合仓库中的实际源码实现与测试用例,完整覆盖其导入方式、参数体系(getter 参数模式、config覆盖、mutation 选项)、返回类型字段,以及底层disconnectaction 对多连接状态机、事件监听器和 recentConnector 存储的处理逻辑,帮助你在 Solid 项目中正确、可复现地实现连接断开功能。
一、原语定位与导入
useDisconnect位于packages/solid/src/primitives目录,与useConnect、useReconnect、useSwitchConnection等连接管理类原语并列。它本质上是对底层disconnectaction 的响应式封装:内部通过 TanStack Query for Solid 的createMutation创建一个可触发、带状态跟踪(pending/error/success)的 mutation,从而让断开连接这一"写操作"拥有完整的生命周期状态可供 UI 绑定。
导入方式如下:
import { useDisconnect } from '@wagmi/solid'最小可用示例
import { useDisconnect } from '@wagmi/solid' function App() { const disconnect = useDisconnect() return ( <button onClick={() => disconnect.mutate()}> Disconnect </button> ) }该原语运行需要Config实例。仓库中 Solid 侧的标准配置示例见 solid config 片段:
import { createConfig, http } from '@wagmi/solid' import { mainnet, sepolia } from '@wagmi/solid/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, })配置一般通过WagmiProvider(参见 WagmiProvider 文档)注入到组件树,应用完整可运行的写法可参考 solid-start playground。
二、Parameters:以 getter 函数传参维持 Solid 响应性
useDisconnect的参数类型声明为:
useDisconnect.Parameters useDisconnect.SolidParameters其中SolidParameters是ConfigParameter & DisconnectOptions<context>的Compute计算结果(见 useDisconnect.ts)。
与 React 版本直接接收对象不同,Solid 的 wagmi 原语要求参数以 getter 函数传入,以便在createMutation内部按需、响应式地读取参数值:
useDisconnect(() => ({ config, // mutation options... }))从 实现源码 可以看到这一约定:
export function useDisconnect<context = unknown>( parameters: useDisconnect.Parameters<context> = () => ({}), ): useDisconnect.ReturnType<context> { const config = useConfig(parameters) const mutation = useMutation(() => disconnectMutationOptions(config(), parameters()), ) return mutation as useDisconnect.ReturnType<context> }parameters的默认值是() => ({}),因此useDisconnect()可以不传参数直接调用;每次 mutation 选项重建时,getter 都会被重新求值,这就是 Solid 响应性得以贯通的关键。
config 参数
Config | undefined
Config类型,用于覆盖从最近WagmiProvider上下文获取的配置。解析逻辑在 useConfig.ts 中实现:优先取parameters().config,否则从WagmiContext读取;两者都没有时抛出WagmiProviderNotFoundError。也就是说,只有当你持有独立于 Provider 的 config 实例(如测试或多配置场景)时才需要显式传入。
mutation 参数(TanStack Query 选项)
SolidParameters中还包含 TanStack Query 的 mutation 选项,以下选项受支持:
| 选项 | 类型 | 说明 |
|---|---|---|
gcTime | number \| Infinity \| undefined | 缓存未被使用后在内存中保留的毫秒时长,设为Infinity则禁用垃圾回收 |
meta | Record<string, unknown> \| undefined | 附加到 mutation 缓存条目的元信息,可在onError/onSuccess等回调中通过 context 访问 |
networkMode | 'online' \| 'always' \| 'offlineFirst' \| undefined | 默认'online',控制 mutation 与网络状态的关系 |
onError | (error, variables, context?) => Promise<unknown> \| unknown | mutation 失败时触发,接收错误对象 |
onMutate | (variables) => Promise<context \| void> \| context \| void | mutation 执行前触发,可用于乐观更新;返回值会传递给onError和onSettled以便回滚 |
onSuccess | (data, variables, context?) => Promise<unknown> \| unknown | mutation 成功后触发,接收结果 |
onSettled | (data, error, variables, context?) => Promise<unknown> \| unknown | 无论成功或失败都会触发 |
queryClient | QueryClient | 使用自定义QueryClient;否则使用最近上下文中提供的实例 |
retry | boolean \| number \| ((failureCount, error) => boolean) | 默认0;false不重试,true无限重试,数字为最大失败次数 |
retryDelay | number \| ((retryAttempt, error) => number) | 指定重试前等待的毫秒数,可用函数实现线性/指数退避 |
需要特别注意的限制:wagmi 不允许覆盖所有 TanStack Query 参数。从 solid 侧查询工具类型 可以看到,SolidMutationParameters显式剔除了mutationFn、mutationKey和throwOnError三个字段——它们在 wagmi 内部使用,用于装配 mutation 行为,用户传入会被忽略。完整的选项说明可参考共享文档 mutation-options。
三、Return Type:完整的 mutation 状态对象
返回类型声明为:
useDisconnect.ReturnType从类型定义看,它由UseMutationReturnType<DisconnectData, DisconnectErrorType, DisconnectVariables, context, DisconnectMutate, DisconnectMutateAsync>计算而来(见 useDisconnect.ts),其中TData为void、TError为DisconnectErrorType、TVariables为{ connector?: Connector | undefined }。
主要字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
mutate | (variables: TVariables, { onSuccess, onSettled, onError }) => void | 触发断开连接的入口函数。variables即传给底层disconnectaction 的参数;回调与参数侧选项等价,仅作用于本次调用 |
mutateAsync | (variables, { onSuccess, onSettled, onError }) => Promise<TData> | 同mutate,但返回可await的 Promise |
data | void \| undefined | 上次成功 resolve 的数据(disconnect 无返回值,恒为undefined) |
error | DisconnectErrorType \| null | 上次尝试的错误对象 |
failureCount | number | 失败次数,每次失败递增,成功后归零 |
failureReason | DisconnectErrorType \| null | 触发重试的失败原因,成功后重置为null |
isError/isIdle/isPending/isSuccess | boolean | 由status派生的布尔标志 |
isPaused | boolean | mutation 处于 paused 状态(网络模式相关)时为true |
reset | () => void | 将 mutation 内部状态重置回初始状态 |
status | 'idle' \| 'pending' \| 'error' \| 'success' | 'idle'初始态;'pending'执行中;'error'最近一次失败;'success'最近一次成功 |
submittedAt | number | mutation 提交时间戳,默认0 |
variables | TVariables \| undefined | 传给mutate的 variables,默认undefined |
典型的 UI 用法:用disconnect.isPending禁用按钮防止重复点击,用onSuccess/onSettled回调或 Solid 信号观察status更新连接面板。更完整的字段说明见共享文档 mutation-result。
错误类型
DisconnectErrorType在 core 的 disconnect action 中定义为:
export type DisconnectErrorType = | ConnectorNotFoundErrorType | ConnectorNotConnectedErrorType // base | BaseErrorType | ErrorType即可能遇到"连接器不存在"(connector参数指向未注册的 uid)或"连接器未连接"(当前连接状态不是 connected)等具体错误,以及基础错误类型。处理断开连接错误时可据此做类型收窄。
四、源码纵深:从原语到 action 的完整调用链
useDisconnect的完整调用链为:useDisconnect(solid primitive)→disconnectMutationOptions(query 层)→disconnect(core action)。逐层拆解如下。
1. mutation 装配层:disconnectMutationOptions
core 的 query 层实现:
export function disconnectMutationOptions<config extends Config, context>( config: config, options: DisconnectOptions<context> = {}, ): DisconnectMutationOptions { return { ...(options.mutation as any), mutationFn: async (variables) => { return disconnect(config, variables) }, mutationKey: ['disconnect'], } }两个要点:一是用户的mutation选项被展开在前,mutationFn与mutationKey由 wagmi 固定写入,这解释了为何这两个字段不可覆盖;二是mutationKey恒为['disconnect'],即所有useDisconnect调用共享同一个 mutation 缓存条目。DisconnectData = DisconnectReturnType(即void),DisconnectVariables = DisconnectParameters | undefined(即可选的{ connector })。
2. action 层:disconnect的状态机逻辑
core action 实现 是整个断开的核心,逻辑分四步:
- 解析目标 connector:若
parameters.connector存在则使用它;否则从config.state中读取当前连接(connections.get(current))对应的 connector。 - 断开并重新绑定监听器:调用
connector.disconnect()后,移除该 connector 上change和disconnect事件对 config 内部 handler 的订阅,但重新挂载connect事件——这样钱包再次连接时能恢复状态同步,而不是"死掉"。 - 更新连接状态机:从
connectionsMap 中删除该连接后,config.setState分两种情况:- 若已无任何连接(
connections.size === 0),整体进入disconnected状态,current置null; - 若仍有多连接(multi-account 场景),自动切换到 Map 中剩余的下一个连接,
current指向它的 uid。
- 若已无任何连接(
- 持久化 recent connector:若断开后仍存在
current连接,则把当前 connector 的id写入config.storage的recentConnectorId,供下次useConnect时的"最近使用"推荐。
从源码结构看,disconnect是幂等且安全的:即使传入一个未连接的 connector uid,也不会抛出异常,而是走"无操作"分支——但类型层面仍保留了ConnectorNotFoundErrorType等错误声明,供调用方做防御式处理。
3. 参数 getter 为何是必须的
回到 solid primitive 实现,useMutation(() => disconnectMutationOptions(config(), parameters()))把config()与parameters()都放在 getter 内,意味着 TanStack Solid 的 mutation 选项会在其依赖变化时重新计算——如果你在 getter 中引用了会变化的信号(例如动态选择的 config 或条件性 mutation 选项),mutation 会自动跟随更新。这是 Solid 版本 wagmi 与 React 版本在参数传递上的本质差异。
五、测试验证:断开后连接状态如何变化
useDisconnect 的测试用例 验证了完整的断开语义:
test('default', async () => { const { result } = renderPrimitive(() => ({ useConnection: useConnection(), useDisconnect: useDisconnect(), })) expect(result.useConnection().address).toBeDefined() expect(result.useConnection().status).toEqual('connected') result.useDisconnect.mutate() await vi.waitFor(() => expect(result.useConnection().isDisconnected).toBeTruthy(), ) expect(result.useConnection().address).not.toBeDefined() expect(result.useConnection().status).toEqual('disconnected') })测试流程:beforeEach中先用@wagmi/core的connectaction 建立连接(config.connectors[0]),断言useConnection状态为connected且address有值;随后调用result.useDisconnect.mutate()(不传 variables,即断开当前连接);最后断言useConnection转为isDisconnected、address为undefined、status为'disconnected'。这个用例恰好印证了第四节的结论:断开后连接被从connectionsMap 中移除,config 状态回到disconnected,且这一变化是响应式地暴露给所有观察连接状态的原语(如useConnection)的。
六、与 TanStack Query 的类型协作
如果你需要在非 Solid 场景(如 Solid 组件外的普通代码)复用断开逻辑,或想在自己的 SolidQuery 工具中复用这些类型,@wagmi/solid/query子路径导出了 disconnect 相关的完整类型集(见共享文档 mutation-imports 的模式,对应 solid 包的实际导出):
import { type DisconnectData, type DisconnectVariables, type DisconnectMutate, type DisconnectMutateAsync, disconnectMutationOptions, } from '@wagmi/solid/query'其中disconnectMutationOptions(config, options)可脱离原语单独用于手动装配createMutation,而DisconnectMutate/DisconnectMutateAsync是注入到返回类型中的精确mutate/mutateAsync函数签名类型。
七、小结
- 导入与调用:
import { useDisconnect } from '@wagmi/solid',disconnect.mutate()断开当前连接,disconnect.mutateAsync({ connector })可断开指定连接器并等待完成。 - 参数:必须以 getter 函数传入;
config用于覆盖 Provider 配置;支持完整 TanStack Query mutation 选项,但mutationFn、mutationKey、throwOnError不可覆盖。 - 返回:标准 mutation 状态对象(
status/isPending/error/mutate/mutateAsync/reset等),TData为void。 - 底层行为:断开指定或当前 connector、重绑
connect监听以支持重连、按多连接情况切换current或回到disconnected、并持久化recentConnectorId。 - 参考路径:文档 useDisconnect.md、原语 useDisconnect.ts、query 层 disconnect.ts、action disconnect.ts、测试 useDisconnect.test.ts、底层 action 文档 disconnect。
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考