I'm learning how to create web3 app with Metamask and react.js
I used create-react-app and follow https://github.com/ChainSafe/web3.js#troubleshooting-and-known-issues to solve errors around polyfill.
Then I followed https://docs.metamask.io/guide/onboarding-library.html#using-react to use Metamsk with react.
DOM does render as expected when metamask is not installed to a browser, but does NOT render when installed. It goes only <div id='root></div>
in body tag.
Why does not rendered only when Metamask is installed? Any idea?
App.js is
import React from 'react';
import './App.css';
import Header from './components/Header/Header';
import Main from './components/Main/Main';
import Description from './components/Description/Description';
const App = () => {
return (
<div>
<Header />
<Main />
<Description />
</div>
)
}
export default App
Main.jsx
import './main.css';
import React, { useState, useEffect, useRef } from 'react'
import Web3 from 'web3';
import OnboardingButton from './OnboardingButton'
const Main = () => {
return (
<div className="container container__main">
<OnboardingButton />
</div>
)
}
export default Main
OnboardingButton.jsx
import React, { useState, useEffect, useRef } from 'react'
import MetaMaskOnboarding from '@metamask/onboarding';
const ONBOARD_TEXT = 'Click here to install Metamask.'
const CONNECT_TEXT = 'Connect';
const CONNECTED_TEXT = 'Connected';
const OnboardingButton = () => {
const [buttonText, setButtonText] = useState(ONBOARD_TEXT);
const [isDisabled, setDisabled] = useState(false);
const [accounts, setAccounts] = useState([]);
const onboarding = useRef();
// execute only when DOM initialized
useEffect(() => {
if (!onboarding.current) {
onboarding.current = new MetaMaskOnboarding();
}
}, []);
useEffect(() => {
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
if (accounts.length > 0) {
setButtonText(CONNECTED_TEXT);
setDisabled(true);
onboarding.current.stopOnboarding();
} else {
setButtonText(CONNECT_TEXT);
setDisabled(false);
}
}
}, [accounts]);
useEffect(() => {
function handleNewAccounts(newAccounts) {
setAccounts(newAccounts);
}
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
window.ethereum.on('accountsChanged', handleNewAccounts);
return () => {
window.ethereum.off('accountsChanged', handleNewAccounts);
};
}
}, []);
const onClick = () => {
if (MetaMaskOnboarding.isMetaMaskInstalled()) {
window.ethereum
.request({ method: 'eth_requestAccounts' })
.then((newAccounts) => setAccounts(newAccounts));
} else {
onboarding.current.startOnboarding();
}
};
return (
<button disabled={isDisabled} onClick={onClick}>
{buttonText}
</button>
);
}
export default OnboardingButton
package.json dependencies
"dependencies": {
"@metamask/onboarding": "^1.0.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"web3": "^1.7.4"
}