“一种 useEffect 没有被执行”

huangapple go评论55阅读模式
英文:

One of two useEffect is not getting executed

问题

在下面的代码中,我声明了两个useEffect,都使用了空的依赖数组。第一个useEffect没有被执行。如果我交换这两个useEffect的顺序,无论哪一个先出现都不会被执行。

发生了什么?我该如何修复这个问题?

英文:

In the below code, I declare two useEffects, both with empty dependency array. The first useEffect is not getting executed. If I switch the order of the two useEffects, and whichever one comes first doesn't get executed.

What's going on? How can I fix this?

import React, {createContext, useState, useEffect, useRef, useContext} from 'react'
import { ethers } from 'ethers'
import Web3Modal from 'web3modal'
import { useNavigate } from 'react-router-dom'
import { ABI, ADDRESS } from '../contract'

//globally storing the state variable so that we can acces on any page and any component

const GlobalContext = createContext()

export const GlobalContextProvider = ({children})=>{
    //interact and connect with our smart contract

    const [walletAddress, setWalletAddress] = useState('')
    const [provider, setprovider] = useState('')
    const [contract, setcontract] = useState(null)
    const [showAlert, setshowAlert] = useState({status: false, type: 'info', message: ''})

    //set the walletAddress to the state
    const updateCurrentWalletAddress = async ()=>{
        //window.ethereum object injects web3 functionality in browser
        //getting all account addresses
        const accounts = await window.ethereum.request({method : 'eth_requestAccounts'})

        console.log("Hello from updateCurrentWalletAddress")
        if(accounts) setWalletAddress(accounts[0]) 
    }
   

    useEffect(() => {
      updateCurrentWalletAddress()
      window.ethereum.on('accountsChanged', updateCurrentWalletAddress)
    }, [])

    
    //set the smart contract and provider to the state
    useEffect(() => {
      const setsmartContractAndProvider = async ()=>{
        //connecting to wallet
        const web3Modal = new Web3Modal()
        const connection = await web3Modal.connect()
        const newProvider = new ethers.providers.Web3Provider(connection)
        const signer = newProvider.getSigner()
        //getting instance of smart contract
        console.log("Hello from setsmartContractAndProvider")
        console.log({signer})
        console.log({walletAddress})
        const newContract = new ethers.Contract(ADDRESS, ABI, signer)
        setprovider(newProvider)
        setcontract(newContract)
      }
      setsmartContractAndProvider()

    }, [])

    
    useEffect(() => {
      if(showAlert?.status){
        const timer = setTimeout(()=>{
          setshowAlert ({status: false, type: 'info', message: ''})
        }, [5000])
        //always good to clear timers when setting them in useEffect
        return ()=> clearTimeout(timer)
      }
    }, [showAlert])
    
    

    //values of variables declared in "value" field is stored globally
    //we can access it by importing useGlobalContext()
    return(
      <GlobalContext.Provider value={{
        contract, walletAddress, showAlert, setshowAlert
      }}>
        {/*children are <Home />, <CreateBattle /> etc  */}
        {children}
      </GlobalContext.Provider>
    )
}

//useContext hook is used to manage state globally
export const useGlobalContext = ()=> useContext(GlobalContext)

答案1

得分: 1

我假设通过将这些功能分离到不同的useEffect钩子中,代码更易于阅读、理解和维护,

您面临的问题是因为第二个useEffect钩子阻塞了事件循环,因此在第二个useEffect钩子完成之前,第一个useEffect钩子无法执行。
将第一个和第二个useEffect钩子的逻辑合并到一个useEffect钩子中。这将确保逻辑按正确顺序运行,并且第一个钩子不会被第二个钩子阻塞。

useEffect(() => {
  const updateCurrentWalletAddress = async () => {
    const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
    if (accounts) setWalletAddress(accounts[0]);
  };

  const setsmartContractAndProvider = async () => {
    const web3Modal = new Web3Modal();
    const connection = await web3Modal.connect();
    const newProvider = new ethers.providers.Web3Provider(connection);
    const signer = newProvider.getSigner();
    const newContract = new ethers.Contract(ADDRESS, ABI, signer);
    setprovider(newProvider);
    setcontract(newContract);
  };

  updateCurrentWalletAddress();
  window.ethereum.on('accountsChanged', updateCurrentWalletAddress);
  setsmartContractAndProvider();
}, []);
英文:

I assume by separating these functionalities into different useEffect hooks, the code is easier to read, understand and maintain,
BUT
The issue you are facing is because the second useEffect hook is blocking the event loop, so the first useEffect hook cannot execute until the second useEffect hook has completed.
Combine the logic of the first and second useEffect hooks into a single useEffect hook. This will ensure that the logic runs in the correct order, and the first hook won't be blocked by the second hook.

useEffect(() => {
  const updateCurrentWalletAddress = async () => {
    const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
    if (accounts) setWalletAddress(accounts[0]);
  };

  const setsmartContractAndProvider = async () => {
    const web3Modal = new Web3Modal();
    const connection = await web3Modal.connect();
    const newProvider = new ethers.providers.Web3Provider(connection);
    const signer = newProvider.getSigner();
    const newContract = new ethers.Contract(ADDRESS, ABI, signer);
    setprovider(newProvider);
    setcontract(newContract);
  };

  updateCurrentWalletAddress();
  window.ethereum.on('accountsChanged', updateCurrentWalletAddress);
  setsmartContractAndProvider();
}, []);

huangapple
  • 本文由 发表于 2023年4月19日 17:15:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76052754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定