4

am trying to build a web3 application. In my frontend I want to detect if user changed his account on Metamask wallet or disconnected and want to show this change on frontend. How can I do so?

  const [account, setaccount] = useState('0x0');
  window.ethereum.on('accountsChanged',async (accounts) =>{
    const changedAccounts =await window.ethereum.request({method: 'eth_requestAccounts'});
    setaccount(changedAccounts[0]);
    console.log('changedAccounts')
  })
  useEffect(async () => {
    if(!window.ethereum){
      window.alert('Please consider installing Metamask');
    }else{
      const accounts =await window.ethereum.request({method: 'eth_requestAccounts'});
      setaccount(accounts[0]);
    }
    if(!window.ethereum.isConnected()){
      console.log('Disconnected')
    }else{
      console.log('Connected')
    }
    console.log('useEffect')
  }, [account]);
  

enter image description here enter image description here

1 Answer 1

4

There are more events to listen to cover all use cases. In addition, the event subscription and cleanup should be moved into a useEffect in order to stop memory leaks.

This is an example that might get you started...

const [account, setaccount] = useState('0x0');
useEffect(() => {
  if (!window.ethereum) {
    // Nothing to do here... no ethereum provider found
    return;
  }
  const accountWasChanged = (accounts) => {
    setaccount(accounts[0]);
    console.log('accountWasChanged');
  }
  const getAndSetAccount = async () => {
    const changedAccounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
    setaccount(changedAccounts[0]);
    console.log('getAndSetAccount');
  }
  const clearAccount = () => {
    setaccount('0x0');
    console.log('clearAccount');
  };
  window.ethereum.on('accountsChanged', accountWasChanged);
  window.ethereum.on('connect', getAndSetAccount);
  window.ethereum.on('disconnect', clearAccount);
  window.ethereum.request({ method: 'eth_requestAccounts' }).then(accounts => {
    console.log('accounts', accounts);
    // No need to set account here, it will be set by the event listener
  }, error => {
    // Handle any UI for errors here, e.g. network error, rejected request, etc.
    // Set state as needed 
  })
  return () => {
    // Return function of a non-async useEffect will clean up on component leaving screen, or from re-reneder to due dependency change
    window.ethereum.off('accountsChanged', accountWasChanged);
    window.ethereum.off('connect', getAndSetAccount);
    window.ethereum.off('disconnect', clearAccount);
  }
}, [/* empty array to avoid re-request on every render, but if you have state related to a connect button, put here */]);
2
  • But if I connect two or more accounts to the website and then disconnect the one that is currently active. Then the state account be equal to the other connected account and that will be reflected on the frontend. Even though we disconnected current account. How to handle this case? Commented Feb 2, 2022 at 16:58
  • You will receive a accountsChanged event that you can handle to update your application state Commented Feb 2, 2022 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.