iicaptain
iicaptain

Reputation: 1195

Using web3 from MetaMask in React

I'm attempting to use the web3 from MetaMask in a React js app like so:

import Web3 from 'web3';

    componentDidMount(){
            if (typeof web3 !== 'undefined') {
                console.log(web3.currentProvider);
                    // Use Mist/MetaMask's provider
                    var web3js = new Web3(web3.currentProvider);

                    web3.version.getNetwork((err, netId) => {
                    switch (netId) {
                        case "1":
                            console.log('This is mainnet')
                            break
                        case "2":
                            console.log('This is the deprecated Morden test network.')
                            break
                        case "3":
                            console.log('This is the ropsten test network.')
                            break
                        case "4":
                            console.log('This is the Rinkeby test network.')
                            break
                        case "42":
                            console.log('This is the Kovan test network.')
                            break
                        default:
                            console.log('This is an unknown network.')
                    }
                })
            } else {
                    console.log('No web3? You should consider trying MetaMask!')
            }           
        }

This the output I get in the dev console in chrome:

enter image description here

Clearly at some point web3 is being properly defined by MetaMask based on the first two lines but then react throws an error saying web3 isn't defined for the instances it appears inside if(typeof web3 !== 'undefined'). Everything I've tried results in the same error or web3 not loading.

Upvotes: 7

Views: 14105

Answers (4)

Ben
Ben

Reputation: 2706

Please note that as of November of 2018, there has been a breaking change to MetaMask where MetaMask will no longer automatically inject web3 into the browser. Instead users must grant the DApp access to their accounts via accepting a prompt dialog created by window.ethereum.enable(). See the below code for handling MetaMask in both modern DApp browsers as well as legacy DApp browsers.

// Modern DApp Browsers
if (window.ethereum) {
   web3 = new Web3(window.ethereum);
   try { 
      window.ethereum.enable().then(function() {
          // User has allowed account access to DApp...
      });
   } catch(e) {
      // User has denied account access to DApp...
   }
}
// Legacy DApp Browsers
else if (window.web3) {
    web3 = new Web3(window.web3.currentProvider);
}
// Non-DApp Browsers
else {
    alert('You have to install MetaMask !');
}

Upvotes: 7

vanduc1102
vanduc1102

Reputation: 6245

Thanks for the other answers in this question. I refer to them to create this hook in my project.


export function useCheckMetaMaskInstalled() {
  const [installed, setInstalled] = useState(false);
  useEffect(() => {
    if (window.ethereum) {
      setInstalled(true);
    }
  }, []);
  return installed;
}

Upvotes: 0

Sumi Mudgil
Sumi Mudgil

Reputation: 89

To new readers that want to fix this issue, as of January 2021, Metamask has removed it's injected window.web3 API. To use connect your app to Metamask, I'd try something like this

export const connectWallet = async () => {
  if (window.ethereum) { //check if Metamask is installed
        try {
            const address = await window.ethereum.enable(); //connect Metamask
            const obj = {
                    connectedStatus: true,
                    status: "",
                    address: address
                }
                return obj;
             
        } catch (error) {
            return {
                connectedStatus: false,
                status: "🦊 Connect to Metamask using the button on the top right."
            }
        }
        
  } else {
        return {
            connectedStatus: false,
            status: "🦊 You must install Metamask into your browser: https://metamask.io/download.html"
        }
      } 
};

In this tutorial on creating an NFT Minter with React, you can also learn how to call smart contract functions and sign transactions via Metamask! Best of luck :)

Upvotes: 4

YD1m
YD1m

Reputation: 5895

You should use web3 provider like MetaMask in browser. This is script that I use for web3 detection:

window.addEventListener('load', function () {
    if (typeof web3 !== 'undefined') {        
        window.web3 = new Web3(window.web3.currentProvider)

        if (window.web3.currentProvider.isMetaMask === true) {
            window.web3.eth.getAccounts((error, accounts) => {
                if (accounts.length == 0) {
                    // there is no active accounts in MetaMask
                }
                else {
                    // It's ok
                }
            });
        } else {
            // Another web3 provider
        }
    } else {
        // No web 3 provider
    }    
});

Upvotes: 9

Related Questions