React连接MetaMask后余额状态需两次点击更新及useEffect失效问题排查
问题原因及修复方案
问题原因
- React状态更新是异步操作,调用
setWalletAddress(accounts[0])后,walletAddress不会立刻更新为新值。 - 此时立即调用
getBalance(),函数内使用的还是旧的空地址,导致eth_getBalance请求参数无效,无法获取正确余额,addressBalance状态自然不会更新。 - 第二次点击时,
walletAddress已经是第一次连接后的有效地址,getBalance()能正常请求到余额,状态才会更新。
修复方案
方案一:直接传递地址参数给getBalance
修改requestAccount和getBalance函数,将获取到的账户地址直接作为参数传入,不依赖state的更新:
async function requestAccount() { console.log("Requesting account..."); if (window.ethereum) { console.log("detected"); try { const accounts = await window.ethereum.request({ method: "eth_requestAccounts", }); const newAddress = accounts[0]; setWalletAddress(newAddress); // 直接传递新地址给getBalance getBalance(newAddress); } catch (error) { console.log("Error connecting..."); } } else { alert("Meta Mask not detected"); } } // 修改getBalance函数,接收地址参数 function getBalance(address) { window.ethereum .request({ method: "eth_getBalance", params: [address, "latest"], }) .then((result) => { console.log(result); let wei = parseInt(result, 16); let balance = wei / 10 ** 18; setaddressBalance(balance); }); }
方案二:通过useEffect监听地址变化自动获取余额
新增一个useEffect钩子,监听walletAddress的变化,当地址更新时自动触发余额查询:
// 新增监听walletAddress的useEffect useEffect(() => { // 地址不为空时才请求余额 if (walletAddress) { getBalance(); } }, [walletAddress]); 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,交给useEffect处理 } catch (error) { console.log("Error connecting..."); } } else { alert("Meta Mask not detected"); } } // 给getBalance增加空地址判断,避免无效请求 function getBalance() { if (!walletAddress) return; 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); }); }
内容的提问来源于stack exchange,提问作者sneaker
相关产品推荐
相关产品推荐

