Wagmi部署至Vercel后无法读写智能合约,本地运行正常
Wagmi部署至Vercel后无法调用合约读写函数的解决方案
问题背景
本地开发环境中,使用Wagmi可正常读写智能合约属性;但部署到Vercel后,仅能连接钱包,调用合约读写函数时触发报错:
Uncaught (in promise) TypeError: y is not a function
报错位置指向SetUsername.jsx的39行和35行,相关业务代码如下:
import React, { useEffect, useState } from 'react' import {FaTimes} from 'react-icons/fa' import { useContractRead, useContractWrite, usePrepareContractWrite, useWaitForTransaction } from 'wagmi' import { useStateContext } from '../context' const CreatePoll = () => { const {createPoll, setCreatePoll , account, contractAbi, contractAddress, setCandidates } = useStateContext() const [name, setName] = useState('') const [description, setDescription] = useState('') const [image, setImage] = useState('') const { config } = usePrepareContractWrite({ address: contractAddress, abi: contractAbi, functionName: 'addCandidate', args: [name, description, image] }) const {write,data} = useContractWrite(config) const { isSuccess } = useWaitForTransaction({ hash: data?.hash, }) const { refetch: refetchCandidates } = useContractRead({ address: contractAddress, abi: contractAbi, functionName: 'getCandidates', onSuccess(data) { setCandidates(data) }, }); const handleSubmit = async(e) => { e.preventDefault() if(account){ if(!name || !description || !image) return alert('plz fill in the form') await write?.() onClose() } else{ alert('Connect to metamask') } } const onClose = ()=> { setName('') setDescription('') setImage('') setCreatePoll('scale-0') } useEffect(() => { refetchCandidates?.() }, [isSuccess]); return ( <div className={`fixed h-screen w-screen top-0 z-50 left-0 flex items-center justify-center bg-black bg-opacity-50 transform transition-transform duration-400 ${createPoll}`} > <div className="bg-white shadow-xl shadow-black rounded-xl w-10/12 md:w-2/5 h-7/12 p-6"> <form className="flex flex-col" onSubmit={handleSubmit}> <div className="flex flex-row justify-between items-center"> <p className="font-bold text-gray-800">Insert Income Details</p> <button type="button" onClick={onClose} className="border-0 bg-transparent hover:text-md focus:outline-none" > <FaTimes /> </button> </div> <div className="flex flex-row items-center justify-center rounded-lg bg-gray-800 mt-5"> <input type="text" className="block w-full p-2 text-sm text-slate-500 bg-transparent rounded-md border-0 focus:outline-none focuse:ring-0" name="name" placeholder="Name" onChange={(e)=>setName(e.target.value)} value={name} required /> </div> <div className="flex flex-row items-center justify-center rounded-lg bg-gray-800 mt-5"> <textarea type="text" className="block w-full p-2 text-sm text-slate-500 bg-transparent rounded-md border-0 focus:outline-none focuse:ring-0" name="description" placeholder="Description" onChange={(e)=>setDescription(e.target.value)} value={description} required /> </div> <div className="flex flex-row items-center justify-center rounded-lg bg-gray-800 mt-5"> <input type="url" className="block w-full p-2 text-sm text-slate-500 bg-transparent border-0 rounded-md focus:outline-none focuse:ring-0" name="image" placeholder="Image" onChange={(e)=>setImage(e.target.value)} value={image} required /> </div> <div className="flex flex-row items-center justify-center pt-10 rounded-lg"> <button className='btn bg-accent px-10 w-1/2 rounded-full' type='submit'> Submit</button> </div> </form> </div> </div> ) } export default CreatePoll
问题分析
- 代码压缩混淆导致变量异常:Vercel默认开启生产环境代码压缩,
y是压缩后的变量名,实际对应代码中的write或refetchCandidates函数,因未正确初始化导致调用时触发"不是函数"的错误。 - Hook依赖缺失:
usePrepareContractWrite未添加状态依赖,当name/description/image变化时,config未重新生成,导致write函数无效。 - 环境变量配置问题:Vercel上未正确配置合约地址、ABI等环境变量,导致生产环境下无法正确连接合约。
解决方案
1. 补全Hook依赖项
给usePrepareContractWrite添加依赖数组,确保状态更新时重新生成合约调用配置:
const { config } = usePrepareContractWrite({ address: contractAddress, abi: contractAbi, functionName: 'addCandidate', args: [name, description, image], }, [name, description, image, contractAddress, contractAbi]) // 添加依赖
2. 安全调用合约函数
在handleSubmit中增强write函数的存在性检查,避免调用undefined:
const handleSubmit = async(e) => { e.preventDefault() if(account){ if(!name || !description || !image) return alert('plz fill in the form') // 替换原write?.()调用 if (write) { await write() } else { alert('合约调用准备未完成,请重试') } onClose() } else{ alert('Connect to metamask') } }
3. 修正useEffect依赖
给useEffect添加refetchCandidates依赖,确保函数引用变化时能正确触发:
useEffect(() => { refetchCandidates?.() }, [isSuccess, refetchCandidates]) // 添加refetchCandidates到依赖
4. 检查Vercel环境变量
登录Vercel控制台,进入项目的"Settings"->"Environment Variables",确认contractAddress、contractAbi等变量已正确配置,且和本地开发环境一致。
5. 临时关闭代码压缩(排查用)
如果怀疑是压缩导致的问题,可在项目配置文件中关闭压缩(以Next.js为例,修改next.config.js):
module.exports = { compress: false, }
排查完成后建议重新开启压缩,避免影响性能。
内容的提问来源于stack exchange,提问作者Anees K.A
相关产品推荐
相关产品推荐

