Reputation: 1195
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:
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
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
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
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
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