Search code examples
reactjsethereummetamaskweb3-react

How to keep MetaMask connection to the UI persistent with Web3-react?


I am working with web3-react and I cannot figure out how to keep the connection to the MetaMask wallet persistent upon browser refreshes.

This is the code:

// define the injectedConnectors

const injectedConnector = new InjectedConnector({
  supportedChainIds: [
    1, // Mainet
    3, // Ropsten
    4, // Rinkeby
    5, // Goerli
    42, // Kovan
  ],
})

const { chainId, account, activate, active } = useWeb3React()
// activate the wallet
activate(injectedConnector)
console.log(account)
// all good. 

Up to here all is working and I activate my MetaMask wallet as well as I get the account correctly logged, and the active variable is a boolean that changes to true.

The problem is that when I refresh the page the active turns to false and I lose the connection between the UI to the MetaMask wallet. Of course saving active into the browser does not change anything because the connection relies on the active boolean value.

The docs are lacking such information.


Solution

  • Finally found a solution! I was trying to use the example in the official library using ... but for some reason it wasn't working though no error came out. Then I stumbled upon some guy who had the same issue and posted on reddit and got a good answer that works for me. This is the link to the post: https://www.reddit.com/r/ethdev/comments/nw7iyv/displaying_connected_wallet_after_browser_refresh/h5uxl88/?context=3 and this is the code from that post:

    First create a file that holds the injectedConnector called connectors.js:

    import { InjectedConnector } from '@web3-react/injected-connector'
    export const Injected = new InjectedConnector({ supportedNetworks: [1, 3, 4, 5, 42] })
    

    Then create a component that checks if the user already activated the wallet:

    import React, { useEffect, useState } from 'react'
    import { injected } from '../connectors'
    import { useWeb3React } from '@web3-react/core'
    
    function MetamaskProvider({ children }) {
      const { active: networkActive, error: networkError, activate: activateNetwork } = useWeb3React()
      const [loaded, setLoaded] = useState(false)
      useEffect(() => {
        injected
          .isAuthorized()
          .then((isAuthorized) => {
            setLoaded(true)
            if (isAuthorized && !networkActive && !networkError) {
              activateNetwork(injected)
            }
          })
          .catch(() => {
            setLoaded(true)
          })
      }, [activateNetwork, networkActive, networkError])
      if (loaded) {
        return children
      }
      return <>Loading</>
    }
    
    export default MetamaskProvider
    

    And wrap MetamaskProvider around the components you want the wallet to be activated upon refresh:

     return (
        <ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
          <StylesProvider injectFirst>
            <Paper>
              <Router>
                <Web3ReactProvider getLibrary={getLibrary}>
                  <MetamaskProvider>
                  {...children components}
                  </MetamaskProvider>
                </Web3ReactProvider>
              </Router>
            </Paper>
          </StylesProvider>
        </ThemeProvider>
      );