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

React连接MetaMask后余额状态需两次点击更新及useEffect失效问题排查

问题原因及修复方案

问题原因

  • React状态更新是异步操作,调用setWalletAddress(accounts[0])后,walletAddress不会立刻更新为新值。
  • 此时立即调用getBalance(),函数内使用的还是旧的空地址,导致eth_getBalance请求参数无效,无法获取正确余额,addressBalance状态自然不会更新。
  • 第二次点击时,walletAddress已经是第一次连接后的有效地址,getBalance()能正常请求到余额,状态才会更新。

修复方案

方案一:直接传递地址参数给getBalance

修改requestAccount和getBalance函数,将获取到的账户地址直接作为参数传入,不依赖state的更新:

async function requestAccount() {
  console.log("Requesting account...");

  if (window.ethereum) {
    console.log("detected");

    try {
      const accounts = await window.ethereum.request({
        method: "eth_requestAccounts",
      });
      const newAddress = accounts[0];
      setWalletAddress(newAddress);
      // 直接传递新地址给getBalance
      getBalance(newAddress);
    } catch (error) {
      console.log("Error connecting...");
    }
  } else {
    alert("Meta Mask not detected");
  }
}

// 修改getBalance函数,接收地址参数
function getBalance(address) {
  window.ethereum
    .request({
      method: "eth_getBalance",
      params: [address, "latest"],
    })
    .then((result) => {
      console.log(result);
      let wei = parseInt(result, 16);
      let balance = wei / 10 ** 18;
      setaddressBalance(balance);
    });
}

方案二:通过useEffect监听地址变化自动获取余额

新增一个useEffect钩子,监听walletAddress的变化,当地址更新时自动触发余额查询:

// 新增监听walletAddress的useEffect
useEffect(() => {
  // 地址不为空时才请求余额
  if (walletAddress) {
    getBalance();
  }
}, [walletAddress]);

async function requestAccount() {
  console.log("Requesting account...");

  if (window.ethereum) {
    console.log("detected");

    try {
      const accounts = await window.ethereum.request({
        method: "eth_requestAccounts",
      });

      setWalletAddress(accounts[0]);
      // 不再手动调用getBalance,交给useEffect处理
    } catch (error) {
      console.log("Error connecting...");
    }
  } else {
    alert("Meta Mask not detected");
  }
}

// 给getBalance增加空地址判断,避免无效请求
function getBalance() {
  if (!walletAddress) return;
  
  window.ethereum
    .request({
      method: "eth_getBalance",
      params: [walletAddress, "latest"],
    })
    .then((result) => {
      console.log(result);
      let wei = parseInt(result, 16);
      let balance = wei / 10 ** 18;
      setaddressBalance(balance);
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:15:37