如何在网站上自动显示连接的钱包地址而不需要刷新页面

how do I automatically display the connected wallet address on the website without needing to refresh the page

我有一个简单的网站,只有如图所示的连接钱包地址。

现在我的问题是,如果我在 Metamask 上切换到不同的连接钱包,UI 上显示的地址不会改变。这类似于 pancakeswap.finance 在您连接并切换帐户后立即在连接钱包按钮上显示您新连接的钱包地址的方式。

这是我的 React 代码:

import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import "./App.css";

const App = () =>{
  const [currentAccount, setCurrentAccount] = useState("");
  const [userAddress, setUserAddress] = useState("");

  const detailsOn = async () =>{
    const { ethereum } = window;
    const provider = new ethers.providers.Web3Provider(ethereum);
    const signer = provider.getSigner();
    
    const addr = await signer.getAddress();

    setUserAddress(addr.toString());
  }

  const checkIfWalletIsConnected = async () =>{
    try{
      const { ethereum } = window;

      if(!ethereum){
        console.log("Use Metamask!");
      } else{
        console.log("Ethereum object found", ethereum);
        detailsOn();
      }

      const accounts = await ethereum.request({method: 'eth_accounts'});

      if(accounts !== 0){
        const account = accounts[0];
        console.log("Found an authorized account ", account);
        setCurrentAccount(account);
        detailsOn();
      } else{
        console.log("Could not find an authorized account");
      }
    } catch(error){
      console.log(error);
    }
  }

  const connectWallet = async () =>{
    try{
      const { ethereum } = window;

      if(!ethereum){
        alert("Use Metamask!");
      } else{
        const accounts = await ethereum.request({ method: 'eth_requestAccounts'});
        console.log("Account connected ", accounts[0]);

        setCurrentAccount(accounts[0]);
      }
    } catch(error){
      console.log(error);
    }
  }

  useEffect( () =>{

    checkIfWalletIsConnected();
  }, []);

  return (
    <div className="mainContainer">
      <div className="dataContainer">

        <div className="bio">
        Account: {userAddress}
        </div>
        
        {!currentAccount && (
          <button className="generalButton" onClick={connectWallet}>
          Connect Wallet
          </button>
        )}
      </div>
    </div>
  );
}

export default App;

我添加了以下内容,这样 UI 将在用户更改钱包时自动更新而无需刷新页面。

  useEffect( () =>{
    const onNewSigner = async () =>{
      let addr;
      if(window.ethereum){
        const provider = new ethers.providers.Web3Provider(window.ethereum);
        const signer = provider.getSigner();

        addr = await signer.getAddress();

        setUserAddress(addr.toString());
      }
    }

    onNewSigner();
  }, []);

但它什么也没做。

如果我很清楚这个问题,你必须让你的 useEffect 听你的变化 window.ethereum。 试试这个:

useEffect( () =>{
    const onNewSigner = async () =>{
      let addr;
      if(window.ethereum){
        const provider = new ethers.providers.Web3Provider(window.ethereum);
        const signer = provider.getSigner();

        addr = await signer.getAddress();

        setUserAddress(addr.toString());
      }
    }

    onNewSigner();
  }, [window.ethereum]);

只需在您的 useEffect Hook 中使用 eth 作为依赖项,如下所示:

 useEffect( () =>{

    checkIfWalletIsConnected();
  }, [window.ethereum]);

如果 window.ethererum 发生任何变化,使用效果再次运行

来自MetaMask docs

window.ethereum.on('accountsChanged', function (accounts) {
  // Time to reload your interface with accounts[0]!
})

window.ethereum.on('networkChanged', function (networkId) {
  // Time to reload your interface with the new networkId
})

您需要确保在 metamask 进行更改时正确处理 accountsChanged。为了那个

window.ethereum.on('accountsChanged', function () {
 detailsOn();
})