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

ReactJS+Web3JS对接MetaMask:无需刷新监听账户链ID并切换网络

React + Web3JS 实现MetaMask连接与实时状态管理

核心实现代码

import { useState, useEffect } from 'react';
import Web3 from 'web3';

function DAppComponent() {
  const [account, setAccount] = useState('');
  const [chainId, setChainId] = useState('');
  const [web3, setWeb3] = useState(null);

  // 连接MetaMask
  const connectMetaMask = async () => {
    if (!window.ethereum) {
      alert('请先安装MetaMask钱包');
      return;
    }
    try {
      const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
      const currentChainId = await window.ethereum.request({ method: 'eth_chainId' });
      const web3Instance = new Web3(window.ethereum);
      
      setAccount(accounts[0]);
      setChainId(currentChainId);
      setWeb3(web3Instance);
    } catch (error) {
      console.error('连接失败:', error);
    }
  };

  // 监听账户、链ID变更及断开连接
  useEffect(() => {
    if (!window.ethereum) return;

    const handleAccountsChanged = (accounts) => {
      accounts.length ? setAccount(accounts[0]) : resetState();
    };

    const handleChainChanged = (newChainId) => {
      setChainId(newChainId);
      setWeb3(new Web3(window.ethereum));
    };

    const handleDisconnect = () => resetState();

    const resetState = () => {
      setAccount('');
      setChainId('');
      setWeb3(null);
      alert('钱包已断开连接');
    };

    window.ethereum.on('accountsChanged', handleAccountsChanged);
    window.ethereum.on('chainChanged', handleChainChanged);
    window.ethereum.on('disconnect', handleDisconnect);

    return () => {
      window.ethereum.removeListener('accountsChanged', handleAccountsChanged);
      window.ethereum.removeListener('chainChanged', handleChainChanged);
      window.ethereum.removeListener('disconnect', handleDisconnect);
    };
  }, []);

  // 切换网络
  const switchNetwork = async (targetChainId) => {
    if (!window.ethereum) {
      alert('请先安装MetaMask钱包');
      return;
    }
    try {
      await window.ethereum.request({
        method: 'wallet_switchEthereumChain',
        params: [{ chainId: Web3.utils.toHex(targetChainId) }],
      });
    } catch (error) {
      if (error.code === 4902) {
        // 示例:添加BSC测试网,需替换为目标链配置
        await window.ethereum.request({
          method: 'wallet_addEthereumChain',
          params: [
            {
              chainId: Web3.utils.toHex(targetChainId),
              chainName: 'BSC测试网',
              nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 },
              rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545/'],
              blockExplorerUrls: ['https://testnet.bscscan.com/'],
            },
          ],
        });
      } else {
        console.error('切换网络失败:', error);
      }
    }
  };

  return (
    <div>
      {!account ? (
        <button onClick={connectMetaMask}>连接MetaMask</button>
      ) : (
        <div>
          <p>当前账户: {account}</p>
          <p>当前链ID: {chainId}</p>
          <div>
            <button onClick={() => switchNetwork(1)}>切换到以太坊主网(链ID:1)</button>
            <button onClick={() => switchNetwork(97)}>切换到BSC测试网(链ID:97)</button>
          </div>
        </div>
      )}
    </div>
  );
}

export default DAppComponent;

功能说明

  • 实时状态同步:通过MetaMask注入的window.ethereum对象监听accountsChanged、chainChanged、disconnect事件,无需刷新页面即可同步账户切换、网络变更、钱包断开等状态。
  • 网络切换逻辑:调用wallet_switchEthereumChain直接切换网络;若目标链未在MetaMask中添加,自动触发wallet_addEthereumChain引导用户添加,全程无页面刷新。
  • Web3实例适配:链ID变更时自动重新初始化Web3实例,确保与当前网络环境匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:35:57