Home > Net >  State changes after 2 clicks and useEffect also not working
State changes after 2 clicks and useEffect also not working

Time:01-09

I have a basic template of a react website with a button that connects to your metamask wallet and displays the current balance.

I have the classic issue that the state of 'addressBalance' only becomes visible after the second click on the connect wallet button. (Basically: I need to click 2 times to show the changes of the 'addressBalance' state.)

I added a useEffect hook that gets triggered whenever 'addressBalance' state changes however the useEffect also only gets triggered on loading the page & after the second click.

This is my code:

import "./App.css";
import { useState, useEffect } from "react";
import { ethers } from "ethers";

function App() {
  const [walletAddress, setWalletAddress] = useState("");
  const [addressBalance, setaddressBalance] = useState("");

  useEffect(() => {
    console.log("Balance updated:", addressBalance);
  }, [addressBalance]);

  async function requestAccount() {
    console.log("Requesting account...");

    if (window.ethereum) {
      console.log("detected");

      try {
        const accounts = await window.ethereum.request({
          method: "eth_requestAccounts",
        });

        setWalletAddress(accounts[0]);
        getBalance();
      } catch (error) {
        console.log("Error connecting...");
      }
    } else {
      alert("Meta Mask not detected");
    }
  }

  function getBalance() {
    const result = window.ethereum
      .request({
        method: "eth_getBalance",
        params: [walletAddress, "latest"],
      })
      .then((result) => {
        console.log(result);
        let wei = parseInt(result, 16);
        let balance = wei / 10 ** 18;
        setaddressBalance(balance);
      });
  }

  async function connectWallet() {
    if (typeof window.ethereum !== "undefined") {
      await requestAccount();

      const provider = new ethers.providers.Web3Provider(window.ethereum);
    }
  }

  return (
    <div className="App">
      <header className="App-header">
        <button className="request-account" onClick={requestAccount}>
          Request Account
        </button>
        <h3>Wallet Address: {walletAddress}</h3>
        <h3>
          {!walletAddress
            ? "No address connected..."
            : `Balance: ${addressBalance} ETH`}
        </h3>
      </header>
    </div>
  );
}

export default App;

I'd like to know how it is possible that the useEffect hook isn't triggered after the first click and how I can fix this problem.

CodePudding user response:

Your useEffect hook isn't getting triggered on the first click because when you call setWalletAddress, your getBalance function immediately tries to access the value of walletAddress but because of React's "asynchronous" state update behavior, the walletAddress variable hasn't been updated to accounts[0] by the time you've called getBalance().

An easy way to fix this is to pass the wallet address as an explicit parameter to getBalance:

 async function requestAccount() {
    console.log("Requesting account...");

    if (window.ethereum) {
      console.log("detected");

      try {
        const accounts = await window.ethereum.request({
          method: "eth_requestAccounts",
        });

        setWalletAddress(accounts[0]);
        getBalance(accounts[0]);
      } catch (error) {
        console.log("Error connecting...");
      }
    } else {
      alert("Meta Mask not detected");
    }
  }

  function getBalance(walletAddress) {
    const result = window.ethereum
      .request({
        method: "eth_getBalance",
        params: [walletAddress, "latest"],
      })
      .then((result) => {
        console.log(result);
        let wei = parseInt(result, 16);
        let balance = wei / 10 ** 18;
        setaddressBalance(balance);
      });
  }

  • Related