Search code examples
reactjsevent-handlingrendering

Why does React fires console.logs 8 times when an event is triggered?


I am new to React and I do not understand why my app render 2 or 8 times.
I am using window.ethereum to interact with MetaMask and have a listener that fires when I change one account in MetaMask. This should fire the console.logs only one time each but they are getting fired 8 times. If I delete the useEffect they are fired 2 times. No other useEffects in all app.

useEffect((loading) => {
    let isMounted = true;
    setDarkMode(JSON.parse(localStorage.getItem('isDark')));
    setLoading(true);
    loadBloackchainData(isMounted, loading);
    // cleanup
    return () => (isMounted = false);
  }, []);

  const ethereum = window.ethereum
  ethereum.on('accountsChanged', function (accounts) {
    console.log('is metamask installed?', ethereum.isMetaMask);
    console.log('ethereum.networkVersion : ', ethereum.networkVersion );
    console.log('ethereum.selectedAddress : ', ethereum.selectedAddress );
  });

Why are being fired 8 times?


Solution

  • Maybe you're inadvertently adding a new accountsChanged handler on each render?
    Each time you render, you may be adding a new handler, which may be getting called by your app when account info changes. You should maybe subscribe/unsubscribe from that event within a useEffect:

    useEffect(() => {
      const ethereum = window.ethereum  
      const doAccountThings = (accounts) => {
        // do account stuff
      }
      ethereum.on('accountsChanged', doAccountThings)
      return () => {
        // here unsubscribe from the doAccountThings handler,
        // whatever that syntax is.
      }
    }, [])
    

    The useEffect docs describe how and why you might need to use this technique to clean up after a subscription: https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1