问题描述
我目前正在尝试从头开始编写一个 dapp,使用 Dapp 大学的 EthSwap (https://github.com/dappuniversity/eth_swap) 作为模型(基本上是尝试在不查看他的代码的情况下重新创建这个 dapp)。基本上,dapp 只允许您购买 erc20 代币。它似乎确实有效,但它确实很慢。我认为这可能是 react 的问题,因为我目前是该框架的新手,可能已经陷入了一些性能问题。我尝试了以下方法以确保消除其他原因:
- 更改浏览器(Chrome --> Brave)并在两者上安装和使用元掩码
- 从 ganache gui 切换到 ganache-cli
- 我将与 web3 的连接视为一个单独的组件并将其导入,但最后只是将此代码放在 App.js 中
这是我的代码:
// App.js
import './App.css';
import PageNavbar from './components/PageNavbar';
import TokenExchangeForm from './components/TokenExchangeForm';
import Web3 from 'web3';
import { useContext,useState,useEffect } from 'react';
import GenericToken from './abis/GenericToken.json';
import TokenExchange from './abis/TokenExchange.json';
function App() {
const [account,setAccount] = useState('');
const [ethBalance,setEthBalance] = useState('');
const [tokenBalance,setTokenBalance] = useState('');
const [genericToken,setGenericToken] = useState(null);
const [tokenExchange,setTokenExchange] = useState(null);
useEffect(() => {
const init = async () => {
await getWeb3();
await getBlockchainData();
}
init();
});
const getBlockchainData = async () => {
const web3 = window.web3
let retrievedAccounts = await web3.eth.getAccounts();
setAccount(retrievedAccounts[0]);
let ethBalance = await web3.eth.getBalance(retrievedAccounts[0]);
setEthBalance(web3.utils.fromWei(ethBalance.toString(),'Ether'));
let networkId = await web3.eth.net.getId()
let genericTokenData = GenericToken.networks[networkId];
let tokenExchangeData = TokenExchange.networks[networkId];
let genericToken = new web3.eth.Contract(GenericToken.abi,genericTokenData.address);
setGenericToken(genericToken);
let tokenExchange = new web3.eth.Contract(TokenExchange.abi,tokenExchangeData.address);
setTokenExchange(tokenExchange);
let tokenBalance = await genericToken.methods.balanceOf(retrievedAccounts[0]).call();
setTokenBalance(web3.utils.fromWei(tokenBalance.toString(),'Ether'));
}
const getWeb3 = async () => {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum);
try {
await window.ethereum.request({ method: 'eth_requestAccounts' });
} catch (err) {
console.log('Transaction rejected by user:',err)
}
}
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider);
}
else {
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
}
}
let buy = (etherAmount) => {
//const gasEstimate = await tokenExchange.methods.buy().estimateGas({ from: account,value: window.web3.utils.toWei(etherAmount,'ether') });
//const gasPriceEstimate = await window.web3.eth.getGasPrice();
tokenExchange.methods.buy().send({ from: account,'Ether')});
}
return (
<div className="App">
<PageNavbar title='Token Exchange' account={account}/>
<TokenExchangeForm ethBalance={ethBalance} tokenBalance={tokenBalance} buy={buy}></TokenExchangeForm>
</div>
);
}
export default App;
// TokenExchangeForm.js
import Card from 'react-bootstrap/Card';
import Container from 'react-bootstrap/esm/Container';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import { useState } from 'react';
import ExchangeField from './ExchangeField';
const TokenExchangeForm = (props) => {
const [etherValue,setEtherValue] = useState('');
const [tokenValue,setTokenValue] = useState('');
const changeHandlerEth = (event) => {
setEtherValue(event.target.value);
}
const changeHandlerToken = (event) => {
setTokenValue(window.web3.utils.fromWei(etherValue,'Ether'));
}
const submitHandlerBuy = (event) => {
event.preventDefault();
props.buy(etherValue);
}
return(
<Container>
<Card id="centered-form">
<Form onSubmit={submitHandlerBuy}>
<Container>
<br />
<ExchangeField label ='Input' balance={props.ethBalance} value={props.etherValue} onChange={changeHandlerEth} placeholder='0' appendtext ="ETH"/>
<br/>
<ExchangeField label='Output' balance={props.tokenBalance} value={props.tokenValue} onChange={changeHandlerToken} placeholder='0' appendtext="GT"/>
<br />
<Form.Row>
<Form.Label>Exchange Rate</Form.Label>
<Form.Label className='add-space'>1 ETH = 100 GT</Form.Label>
</Form.Row>
<br />
<Button type='submit' variant="primary" size="lg" className ="w-100" block>
SWAP
</Button>
</Container>
</Form>
</Card>
</Container>
);
}
export default TokenExchangeForm;
解决方法
我解决了我的问题。事实证明 useEffect 在每次渲染后都会继续运行,因此它不断地重新加载 web3,从而减慢了应用程序的速度。您可以通过在 useEffect 中添加一个空数组来防止这种情况:
useEffect(() => {
const init = async () => {
await getWeb3();
await getBlockchainData();
}
init();
},[]);
这允许 useEffect 仅在安装组件时运行。查看此帖子以了解更多信息:https://stackoverflow.com/a/53464623/4421062