You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中Wagmi Hook使用报错:vue-query组合式函数仅可在setup内使用

问题:Vue项目中使用Wagmi Hook触发MINT函数时出现多个错误

在Vue项目的Pagename.vue文件中,使用Wagmi的useAccount、useContractRead、useContractWrite等Hook时,点击MINT按钮触发mintNew函数,控制台连续出现三个错误:

  • vue-query组合式函数(如useQuery)只能在setup函数或生效的作用域内使用;
  • [Vue warn]: inject() can only be used inside setup() or functional components;
  • [Vue warn]: Unhandled error during execution of native event handler

相关代码如下:

<template>
<div>
 <button type="button" @click="count++">+</button>
   <input autocomplete="off" type="text" :value="count" disabled />
  <button type="button" autocomplete="off" @click="count--">-</button>
 <button type="submit" autocomplete="off" @click="mintNew(count)">MINT</button>
</div>
</template>

<script setup>
const count = ref(0)

defineExpose({
    count
})

import { useAccount, useContractWrite, useContractRead } from 'use-wagmi'
import  json  from '~/artifacts/contracts/GenTest2.sol/GenTest2.json'

const contract = json
const config  = useRuntimeConfig()
const contractAdd = config.public.contract
const { isConnected } = useAccount()

const thePrice = () => {
    useContractRead({
      address: contractAdd,
      functionName: "T2G_PRICE",
      onSuccess(data) {
        console.log('success', data)
      }
    })
}

async function mintNew(mintCount) {
    const { data, write: T2GMint } = useContractWrite({
    address: contractAdd, 
    abi: contract.abi, 
    functionName: "T2GMint"
    });
    const ethToBeSent = thePrice() * mintCount
    if(!isConnected) {
      alert('Connect Wallet to Mint or Enter amount more than 0')
    }
    else {
      T2GMint({ args: mintCount, value: ethToBeSent})
    }
    return data
}
</script>

错误原因及修复方案

核心问题

Wagmi的所有Hook(基于Vue Query实现)属于Vue组合式API范畴,必须在setup函数的顶层(或其他组合式函数的顶层)调用,不能嵌套在普通函数、事件处理函数内部。你的代码中useContractRead放在了thePrice函数里,useContractWrite放在了mintNew事件处理函数里,违反了这个规则,导致了上述错误。

具体修复步骤

  1. 将useContractRead移到setup顶层,存储合约价格
    用ref变量存储价格,在useContractRead的onSuccess回调中更新这个值:

    const price = ref(0)
    useContractRead({
      address: contractAdd,
      functionName: "T2G_PRICE",
      onSuccess(data) {
        console.log('success', data)
        // 将BigNumber格式转换为可读数值(根据合约实际情况调整)
        price.value = data?.toNumber() || 0
      }
    })
    
  2. 将useContractWrite移到setup顶层,获取写入函数
    在setup顶层初始化合约写入Hook,得到write函数供后续调用:

    const { write: T2GMint, data: mintData } = useContractWrite({
      address: contractAdd, 
      abi: contract.abi, 
      functionName: "T2GMint"
    })
    
  3. 重构mintNew函数,使用预先获取的价格和写入函数
    不需要在函数内部再调用Hook,直接使用setup顶层定义的变量和函数:

    async function mintNew(mintCount) {
      if (!isConnected || mintCount <= 0) {
        alert('请连接钱包或输入大于0的数量')
        return
      }
      // 计算要发送的ETH金额(注意单位转换,合约如果用Wei的话需要处理)
      const ethToBeSent = price.value * mintCount
      // 调用写入函数
      T2GMint({ args: [mintCount], value: ethToBeSent })
      return mintData
    }
    

完整修复后的代码

<template>
<div>
 <button type="button" @click="count++">+</button>
   <input autocomplete="off" type="text" :value="count" disabled />
  <button type="button" autocomplete="off" @click="count--">-</button>
 <button type="submit" autocomplete="off" @click="mintNew(count)">MINT</button>
</div>
</template>

<script setup>
import { ref } from 'vue'
import { useAccount, useContractWrite, useContractRead } from 'use-wagmi'
import json from '~/artifacts/contracts/GenTest2.sol/GenTest2.json'

const count = ref(0)
const price = ref(0)

defineExpose({
    count
})

const contract = json
const config = useRuntimeConfig()
const contractAdd = config.public.contract
const { isConnected } = useAccount()

// 顶层调用useContractRead获取价格
useContractRead({
  address: contractAdd,
  functionName: "T2G_PRICE",
  onSuccess(data) {
    console.log('success', data)
    price.value = data?.toNumber() || 0
  }
})

// 顶层调用useContractWrite获取写入函数
const { write: T2GMint, data: mintData } = useContractWrite({
  address: contractAdd, 
  abi: contract.abi, 
  functionName: "T2GMint"
})

async function mintNew(mintCount) {
  if (!isConnected || mintCount <= 0) {
    alert('请连接钱包或输入大于0的数量')
    return
  }
  const ethToBeSent = price.value * mintCount
  T2GMint({ args: [mintCount], value: ethToBeSent })
  return mintData
}
</script>

额外注意事项

  • 合约返回的价格通常是BigNumber类型,需要根据合约的单位(比如Wei)转换为对应的ETH数值,避免计算错误。
  • 调用T2GMint时,args需要是数组格式(即使只有一个参数),确保和合约函数的参数列表匹配。

内容的提问来源于stack exchange,提问作者Meltxx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 14:10:56