不断的重新渲染是不是会使我的反应 dapp 变慢?还是web3有问题?
Posted
技术标签:
【中文标题】不断的重新渲染是不是会使我的反应 dapp 变慢?还是web3有问题?【英文标题】:Is constant re-rendering making my react dapp slow? Or is it a problem with web3?不断的重新渲染是否会使我的反应 dapp 变慢?还是web3有问题? 【发布时间】:2021-08-28 15:24:48 【问题描述】:我目前正在尝试从头开始编写一个 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, value: window.web3.utils.toWei(etherAmount, '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;
【问题讨论】:
react 非常聪明,如果它返回相同的状态,它不应该在设置时重新渲染。 我在想这也可能是我所做的表单处理。我确实注意到当我按下提交按钮时它变慢了。 【参考方案1】:我解决了我的问题。事实证明,useEffect 在每次渲染后都会继续运行,因此它会不断地重新加载 web3,从而降低应用程序的速度。您可以通过在 useEffect 中添加一个空数组来防止这种情况:
useEffect(() =>
const init = async () =>
await getWeb3();
await getBlockchainData();
init();
, []);
这允许 useEffect 仅在安装组件时运行。查看此帖子以了解更多信息:https://***.com/a/53464623/4421062
【讨论】:
以上是关于不断的重新渲染是不是会使我的反应 dapp 变慢?还是web3有问题?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮?