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

如何监听MetaMask/ethers.js钱包余额变化?

监听React应用中账户余额变化的方案

不用依赖低效的setInterval,有几种更优雅的实时同步方案:

1. 后端主动推送(WebSocket/SSE)

这是最实时的方案,当后端检测到账户余额变化(比如充值完成),主动把新余额推送给前端。在React组件里可以这样实现:

import { useEffect, useState } from 'react';

function BalanceComponent() {
  const [balance, setBalance] = useState(0);

  useEffect(() => {
    // 建立WebSocket连接
    const socket = new WebSocket('ws://your-backend-url/balance-updates');
    
    // 监听后端推送的余额更新消息
    socket.onmessage = (event) => {
      const newBalance = JSON.parse(event.data).balance;
      setBalance(newBalance);
    };

    // 组件卸载时关闭连接
    return () => socket.close();
  }, []);

  return <div>当前余额:{balance}</div>;
}

如果后端支持Server-Sent Events(SSE),也可以用EventSource,实现更轻量,适合单向推送的场景。

2. 全局状态管理订阅

如果用Redux、Zustand这类状态管理库,可以把余额存在全局状态里,充值操作完成后直接更新全局状态,所有订阅该状态的组件会自动刷新:

以Zustand为例:

// store.js
import { create } from 'zustand';

export const useBalanceStore = create((set) => ({
  balance: 0,
  updateBalance: (newBalance) => set({ balance: newBalance }),
}));

// 充值组件
function RechargeComponent() {
  const updateBalance = useBalanceStore((state) => state.updateBalance);

  const handleRecharge = async () => {
    // 调用充值接口
    const response = await fetch('/api/recharge', { method: 'POST', body: ... });
    const data = await response.json();
    // 更新全局余额
    updateBalance(data.newBalance);
  };

  return <button onClick={handleRecharge}>充值</button>;
}

// 余额展示组件
function BalanceDisplay() {
  const balance = useBalanceStore((state) => state.balance);
  return <div>余额:{balance}</div>;
}

3. 充值请求后即时更新

如果不需要全量实时,只是充值完成后同步,最简单的方式是在充值接口调用成功后,直接获取最新余额或者用接口返回的新值更新状态:

function BalanceComponent() {
  const [balance, setBalance] = useState(0);

  const handleRecharge = async () => {
    try {
      const rechargeRes = await fetch('/api/recharge', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ amount: 100 })
      });
      const rechargeData = await rechargeRes.json();
      // 直接用接口返回的新余额更新
      setBalance(rechargeData.newBalance);
      // 或者重新调用余额接口获取最新值
      // const balanceRes = await fetch('/api/balance');
      // const balanceData = await balanceRes.json();
      // setBalance(balanceData.balance);
    } catch (err) {
      console.error('充值失败:', err);
    }
  };

  return (
    <div>
      <div>当前余额:{balance}</div>
      <button onClick={handleRecharge}>充值100元</button>
    </div>
  );
}

4. 优化版轮询(不推荐,但比setInterval好)

如果以上方案都无法实现,非要用轮询,可以用递归的setTimeout替代setInterval,避免请求堆积:

import { useEffect, useState } from 'react';

function BalanceComponent() {
  const [balance, setBalance] = useState(0);

  const fetchBalance = async () => {
    const res = await fetch('/api/balance');
    const data = await res.json();
    setBalance(data.balance);
    // 请求完成后再设置下一次轮询
    setTimeout(fetchBalance, 5000);
  };

  useEffect(() => {
    const timer = setTimeout(fetchBalance, 0);
    return () => clearTimeout(timer);
  }, []);

  return <div>当前余额:{balance}</div>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:55:21