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
相关产品推荐
相关产品推荐

