Using web3modal in class component shows state error

1.4k Views Asked by At

I am using web3modal with walletconnect and portis with the following configuration:

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
 import Web3Modal from "web3modal";
 import Portis from "@portis/web3";
 import WalletConnectProvider from "@walletconnect/web3-provider";

 class App extends Component{
  async getData(){
    const  providerOptions={
            injected:{
              display:{
             name: "Injected",
             description: "Connect with the provider in your Browser"
           },
           package:null
            },
           
            walletconnect:{
              package:WalletConnectProvider,
              options:{
                infuraId:"INFURA_ID"
              }
            },
          
            portis:{
     package:Portis,
     options:{
       id:"PORTIS_ID"
     }
            }
          }
      

     const web3Modal = new Web3Modal({
      network: "mainnet", // optional
      cacheProvider: true, // optional
      providerOptions // required
    });
     const provider = await web3Modal.connect();
  const web3=new Web3(provider)
  const accounts= await web3.eth.getAccounts()
  console.log(accounts)
  this.setState({account:accounts[0]})
      const networkId =  await web3.eth.net.getId()
      const mainNetwork =1
  
  const ethBalance = await web3.eth.getBalance(this.state.account) / 10 ** 18
  this.setState({ ethBalance })
  
  provider.on('accountsChanged', function (accounts) {
    this.setState({address:accounts[0]})
    window.location.reload();
  })
  
  provider.on('chainChanged', function (networkId) {
    window.location.reload();
  })
  provider.on("disconnect",function() {
   provider.close();
   web3Modal.clearCachedProvider();
   provider=null;
  });
}
 constructor(props) {
    super(props)
    this.state = {
    account: '',
    ethBalance:'0',
}

} render(){ return( Get tokens )} }

When I am connecting on mobile, it shows a popup window from where I cam choose the provider. When I'm trying to connect on desktop, nothing pops up and it throws an error on retrieving the balance from the current account "TypeError: Cannot read property 'state' of undefined":

const ethBalance = await web3.eth.getBalance(this.state.account) / 10 ** 18
this.setState({ ethBalance })

How can I get the balance of the current account with web3modal in a class component?

1

There are 1 best solutions below

3
On BEST ANSWER

Your this variable is missing when you need it, because you're calling a function that establishes a new this variable in its scope.

Try changing

async getData() { ...}

to

const getData = async () {...}

I got the idea from React: this is null in event handler, and you can read more there. The highest-scoring answer to that question takes a different approach (actually two different approaches), but I think this is better (from a different answer).

The difference is that arrow functions basically leave this alone when they run. The precise explanation is long (https://web.archive.org/web/20160625172303/http://blog.getify.com/arrow-this/), and maybe you don't need to read it all.