1

我目前正在尝试从头开始编写一个 dapp,使用 Dapp 大学的 EthSwap ( https://github.com/dappuniversity/eth_swap ) 作为模型(基本上是在不查看他的代码的情况下尝试重新创建这个 dapp)。基本上,dapp 只允许你购买 erc20 代币。它似乎确实有效,但它确实很慢。我认为这可能是 react 的一个问题,因为我目前是该框架的新手,并且可能陷入了一些性能问题。我尝试了以下方法以确保消除其他原因:

  1. 更改浏览器(Chrome --> Brave)并在两者上安装和使用元掩码
  2. 从 ganache gui 切换到 ganache-cli
  3. 我将与 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;
4

1 回答 1

0

我解决了我的问题。事实证明,useEffect 在每次渲染后都会继续运行,因此它会不断地重新加载 web3,从而降低应用程序的速度。您可以通过在 useEffect 中添加一个空数组来防止这种情况:

 useEffect(() => {
     const init = async () => {
       await getWeb3();
       await getBlockchainData();
     }
     init();
  }, []);

这允许 useEffect 仅在安装组件时运行。查看这篇文章以了解更多信息:https ://stackoverflow.com/a/53464623/4421062

于 2021-06-11T21:13:23.663 回答