React中web3.js调用合约transferMargin函数时按钮自动触发问题
问题:页面刷新时自动调用合约函数,而非点击按钮触发
尝试通过React/Javascript(web3.js)和Metamask在Optimism Kovan网络调用Synthetix合约的transferMargin()函数,期望点击按钮时执行该合约函数,但页面启动或刷新时openLong()函数会自动调用,而非仅在点击“Chainlink Long”按钮时触发。以下是我的代码:
import react, { useState } from "react"; import { Component } from 'react'; import Web3 from 'web3' export default function KwentaOptimism() { let provider = window.ethereum; let selectedAccount; if (typeof provider !== 'undefined') { provider .request({method: 'eth_requestAccounts' }) .then((accounts) => { selectedAccount = accounts[0]; console.log(`Selected account is ${selectedAccount}`); }) } const web3 = new Web3(provider); async function loadContract(){ let address = "0x1e28378F64bC04E872a9D01Eb261926717346F98"; let chainlinkFutureContractABI = [{"constant":false,"inputs":[{"internalType":"int256","name":"marginDelta","type":"int256"}],"name":"transferMargin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]; var Contract = require('web3-eth-contract'); var chainlinkFutureContract = new Contract(chainlinkFutureContractABI, address); return await chainlinkFutureContract; } async function openLong(){ let linkContract = await loadContract(); linkContract.methods.transferMargin("100000000000000000000").send({from: '0xce05626e35c053995d4988b75af85e2eb7251b3c'}); } return( <div> <br/> <button onclick = {openLong()}>Chainlink Long</button> </div> ) }
原因与解决方案
核心原因
问题出在按钮的事件绑定上:你写的是onclick = {openLong()},这里的openLong()会在组件渲染时立即执行(因为括号()是函数调用语法),而不是等待点击事件触发。另外React中的事件属性是驼峰命名,应该用onClick而非小写的onclick,否则可能无法正确绑定点击逻辑。
修复步骤
- 将按钮的
onclick改为onClick,并去掉函数后的括号,传递函数引用而非直接调用:<button onClick={openLong}>Chainlink Long</button> - 额外优化点:
loadContract函数里不需要await,因为new Contract是同步操作,直接返回实例即可openLong函数中添加try/catch捕获调用异常,方便排查问题- 尽量使用用户授权的
selectedAccount作为交易发起地址,而非硬编码地址
修改后的完整代码
import React, { useState } from "react"; import Web3 from 'web3' export default function KwentaOptimism() { let provider = window.ethereum; let selectedAccount; if (typeof provider !== 'undefined') { provider.request({method: 'eth_requestAccounts' }) .then((accounts) => { selectedAccount = accounts[0]; console.log(`Selected account is ${selectedAccount}`); }) .catch(err => console.error('请求账户失败:', err)); } const web3 = new Web3(provider); function loadContract(){ const address = "0x1e28378F64bC04E872a9D01Eb261926717346F98"; const chainlinkFutureContractABI = [{"constant":false,"inputs":[{"internalType":"int256","name":"marginDelta","type":"int256"}],"name":"transferMargin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]; const Contract = require('web3-eth-contract'); return new Contract(chainlinkFutureContractABI, address); } async function openLong(){ try { const linkContract = loadContract(); await linkContract.methods.transferMargin("100000000000000000000") .send({from: selectedAccount || '0xce05626e35c053995d4988b75af85e2eb7251b3c'}); console.log('保证金转账成功'); } catch (err) { console.error('保证金转账失败:', err); } } return( <div> <br/> <button onClick={openLong}>Chainlink Long</button> </div> ) }
内容的提问来源于stack exchange,提问作者blossom
相关产品推荐
相关产品推荐

