news 2026/9/17 3:01:16

wagmi @wagmi/solid useDisconnect 原语完全指南:在 Solid.js 应用中安全断开钱包连接

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
wagmi @wagmi/solid useDisconnect 原语完全指南:在 Solid.js 应用中安全断开钱包连接

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目录,与useConnectuseReconnectuseSwitchConnection等连接管理类原语并列。它本质上是对底层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

其中SolidParametersConfigParameter & 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 选项,以下选项受支持:

选项类型说明
gcTimenumber \| Infinity \| undefined缓存未被使用后在内存中保留的毫秒时长,设为Infinity则禁用垃圾回收
metaRecord<string, unknown> \| undefined附加到 mutation 缓存条目的元信息,可在onError/onSuccess等回调中通过 context 访问
networkMode'online' \| 'always' \| 'offlineFirst' \| undefined默认'online',控制 mutation 与网络状态的关系
onError(error, variables, context?) => Promise<unknown> \| unknownmutation 失败时触发,接收错误对象
onMutate(variables) => Promise<context \| void> \| context \| voidmutation 执行前触发,可用于乐观更新;返回值会传递给onErroronSettled以便回滚
onSuccess(data, variables, context?) => Promise<unknown> \| unknownmutation 成功后触发,接收结果
onSettled(data, error, variables, context?) => Promise<unknown> \| unknown无论成功或失败都会触发
queryClientQueryClient使用自定义QueryClient;否则使用最近上下文中提供的实例
retryboolean \| number \| ((failureCount, error) => boolean)默认0false不重试,true无限重试,数字为最大失败次数
retryDelaynumber \| ((retryAttempt, error) => number)指定重试前等待的毫秒数,可用函数实现线性/指数退避

需要特别注意的限制:wagmi 不允许覆盖所有 TanStack Query 参数。从 solid 侧查询工具类型 可以看到,SolidMutationParameters显式剔除了mutationFnmutationKeythrowOnError三个字段——它们在 wagmi 内部使用,用于装配 mutation 行为,用户传入会被忽略。完整的选项说明可参考共享文档 mutation-options。

三、Return Type:完整的 mutation 状态对象

返回类型声明为:

useDisconnect.ReturnType

从类型定义看,它由UseMutationReturnType<DisconnectData, DisconnectErrorType, DisconnectVariables, context, DisconnectMutate, DisconnectMutateAsync>计算而来(见 useDisconnect.ts),其中TDatavoidTErrorDisconnectErrorTypeTVariables{ connector?: Connector | undefined }

主要字段如下:

字段类型说明
mutate(variables: TVariables, { onSuccess, onSettled, onError }) => void触发断开连接的入口函数。variables即传给底层disconnectaction 的参数;回调与参数侧选项等价,仅作用于本次调用
mutateAsync(variables, { onSuccess, onSettled, onError }) => Promise<TData>mutate,但返回可await的 Promise
datavoid \| undefined上次成功 resolve 的数据(disconnect 无返回值,恒为undefined
errorDisconnectErrorType \| null上次尝试的错误对象
failureCountnumber失败次数,每次失败递增,成功后归零
failureReasonDisconnectErrorType \| null触发重试的失败原因,成功后重置为null
isError/isIdle/isPending/isSuccessbooleanstatus派生的布尔标志
isPausedbooleanmutation 处于 paused 状态(网络模式相关)时为true
reset() => void将 mutation 内部状态重置回初始状态
status'idle' \| 'pending' \| 'error' \| 'success''idle'初始态;'pending'执行中;'error'最近一次失败;'success'最近一次成功
submittedAtnumbermutation 提交时间戳,默认0
variablesTVariables \| 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选项被展开在前,mutationFnmutationKey由 wagmi 固定写入,这解释了为何这两个字段不可覆盖;二是mutationKey恒为['disconnect'],即所有useDisconnect调用共享同一个 mutation 缓存条目。DisconnectData = DisconnectReturnType(即void),DisconnectVariables = DisconnectParameters | undefined(即可选的{ connector })。

2. action 层:disconnect的状态机逻辑

core action 实现 是整个断开的核心,逻辑分四步:

  1. 解析目标 connector:若parameters.connector存在则使用它;否则从config.state中读取当前连接(connections.get(current))对应的 connector。
  2. 断开并重新绑定监听器:调用connector.disconnect()后,移除该 connector 上changedisconnect事件对 config 内部 handler 的订阅,但重新挂载connect事件——这样钱包再次连接时能恢复状态同步,而不是"死掉"。
  3. 更新连接状态机:从connectionsMap 中删除该连接后,config.setState分两种情况:
    • 若已无任何连接(connections.size === 0),整体进入disconnected状态,currentnull
    • 若仍有多连接(multi-account 场景),自动切换到 Map 中剩余的下一个连接,current指向它的 uid。
  4. 持久化 recent connector:若断开后仍存在current连接,则把当前 connector 的id写入config.storagerecentConnectorId,供下次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/coreconnectaction 建立连接(config.connectors[0]),断言useConnection状态为connectedaddress有值;随后调用result.useDisconnect.mutate()(不传 variables,即断开当前连接);最后断言useConnection转为isDisconnectedaddressundefinedstatus'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 选项,但mutationFnmutationKeythrowOnError不可覆盖。
  • 返回:标准 mutation 状态对象(status/isPending/error/mutate/mutateAsync/reset等),TDatavoid
  • 底层行为:断开指定或当前 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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 3:00:51

从“录完再干”到“边干边录”:沟通型CRM的架构设计与落地实践

做了六七年企业服务类产品&#xff0c;我一直有一个特别深的感触&#xff1a;市面上大多数CRM&#xff0c;本质上不是用来帮销售干活的&#xff0c;而是用来给管理层看报表的。业务员最烦的就是跟进完客户还要回头填一堆表单&#xff0c;系统里记录的信息永远是昨天甚至上周的&…

作者头像 李华
网站建设 2026/9/17 3:00:36

2.8T MoE大模型部署实践:显存工程、量化与分布式切分

1. 这题不是“塞不塞得下”&#xff0c;而是一道显存工程的综合题一个朋友问了我一个听起来特别离谱的需求&#xff1a;要把 2.8T 总参数量的 Kimi K3 部署到 32 张 H20 上。我第一反应是疯了吧&#xff0c;2.8T 参数用 BF16 存&#xff0c;光权重就得 5.6TB&#xff0c;32 张 …

作者头像 李华
网站建设 2026/9/17 3:00:27

LabVIEW与Proteus联合仿真:智能垃圾分类箱上位机开发实战

简介&#xff1a;这是一套融合Keil、Proteus与LabVIEW的智能垃圾分类箱综合仿真方案&#xff0c;面向单片机/嵌入式/测控类课设、电子竞赛及毕设场景&#xff0c;重点解决传感器检测、下位机逻辑与上位机管理的一体化联动问题。压缩包共52个文件、约541KB&#xff0c;含LabVIEW…

作者头像 李华
网站建设 2026/9/17 2:59:55

数据库安全测试实战:人才库篡改模拟与伦理复盘

凌晨两点&#xff0c;我在测试环境里把一条候选人状态的字段从“面试通过”改成了“已淘汰”&#xff0c;然后用管理员账号登录系统&#xff0c;看到HR页面里这个人已经消失在后备列表里。那一刻我意识到&#xff0c;我做的这个动作&#xff0c;和真实入侵者做的动作&#xff0…

作者头像 李华
网站建设 2026/9/17 2:59:48

WinForm界面美化实战:从零实现自绘控件与主题系统

很多人对WinForm的印象还停留在“灰底白键、年代感十足”的老式桌面程序&#xff0c;打开新版Visual Studio拖几个Button和TextBox&#xff0c;默认风格确实谈不上好看。但这并不是WinForm的天花板。前阵子接手一个项目&#xff0c;客户明确提出界面太“土”&#xff0c;要求在…

作者头像 李华
网站建设 2026/9/17 2:59:45

Redis事务为何不支持回滚?深度解析设计取舍与工程实践

一两年前我去一家做电商中台的公司面试&#xff0c;聊到缓存层设计时&#xff0c;面试官忽然抛出一句&#xff1a;“Redis 的事务明明不支持回滚&#xff0c;为什么还叫事务&#xff1f;”我当场愣了一下&#xff0c;因为 Redis 事务确实和我们熟悉的“ACID 事务”不是一回事。…

作者头像 李华