0

After inserting const web3React = useWeb3React(); into my App.js component, I get the following error message.

React Hook "useWeb3React" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function. enter image description here

Code Snippet:

import React, { useEffect } from "react";
import { useWeb3React, Web3ReactProvider } from "@web3-react/core";
import Web3 from "web3";

import SmartContractManagementComponent from "./components/SmartContractManagementComponent";
import Navbar from "./components/Navbar";
import CreateContract from "./components/CreateContract";
import TransactionDashboard from "./components/TransactionDashboard";
import Footer from "./components/Footer";
import { WalletConnector } from "./components/wallet/WalletConnector";

const App = () => {
useEffect(() => {
    const web3React = useWeb3React();
  }, []);

  const getLibrary = (provider) => {
    return new Web3(provider);
  };

  return (

    <Web3ReactProvider getLibrary={getLibrary}>
      <div className='App'>
        <Navbar />
        <WalletConnector />
        <div className='flex flex-row w-full'>
          <CreateContract className='flex w-1/2' />
          <TransactionDashboard className='flex w-1/2' />
        </div>

        <Footer />
      </div>
    </Web3ReactProvider>
  );
};

Can anybody explain what I'm doing wrong to access the useWeb3React-Hook? I thought it useful to call the hook just after the other components have been mounted so that MetaMask will already be injected.

1 Answer 1

1

useWeb3React() cannot be called inside useEffect callback, or any callback. It needs to be top level inside the component. So it needs to be like this:

const App = () => {
  const web3React = useWeb3React();
...
}

which means you don't need useEffect for setting up useWeb3React.

You can also take the getLibrary function outside of the component since it only needs to be called once to get the library:

const getLibrary = (provider) => {
  return new Web3(provider);
};

const App = () => {
  const web3React = useWeb3React();
  return (
    <Web3ReactProvider getLibrary={getLibrary}>
     ...
    </Web3ReactProvider>
  );
}

If you want to wait until components have been mounted you can create a hasMounted boolean and update it to true inside useEffect. That way you have something to check against and verify components have mounted:

...

const App = () => {
  ...

  const [hasMounted, setHasMounted] = React.useState(false)
  React.useEffect(() => {
    setHasMounted(true)
  }, [])

  return (
    <>
      {hasMounted && (
        <Web3ReactProvider getLibrary={getLibrary}>
          <div className='App'>
            ...
          </div>
        </Web3ReactProvider>
      )}
    </>
  )
}

Your Answer

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

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