英文:
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();
}, []);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论