获取中的 React 函数

React function inside a fetching

我列出了一个包含很多行的 table,我想根据 {transaction.to_address} 值

在每一行中使用一个新函数

我想在抓取函数中使用 useeffect() 函数,但我收到以下错误消息: 渲染了比之前渲染更多的钩子。 我已经尝试了很多我在这里找到的解决方案,我花了将近一整天的时间,但我不够聪明,无法修复它。

export default function Transactions({user}){
    
    const Web3Api = useMoralisWeb3Api()
    const [transactions, setTransactions] = useState()
    const BASE_URL = "https://bscscan.com/tx/"


    const fetchTransactions = async () => {
        const data = await Web3Api.account.getTransactions({
            chain: "bsc",
            address: user.get('wallet2')
        })
        if(data) {
            setTransactions(data.result)
        }
    }
   

    useEffect(() => {
        fetchTransactions()
    }, [])

    return(
            <TableContainer>
            <Table variant='simple'>
                <TableCaption>TRANSACTIONS</TableCaption>
                <Thead>
                <Tr>
                    <Th>#</Th>
                    <Th>TYPE</Th>
                    <Th>GAS</Th>
                    <Th>VALUE</Th>
                    <Th>4</Th>
                    <Th>5</Th>
                    <Th>Value</Th>
                 </Tr>
                </Thead>
                <Tbody>
                {transactions && transactions.map(transaction => (
                  transaction.value >= 1 ?    
                    <Tr key={transaction.hash}>
                        <Th><Link href={`${BASE_URL}${transaction.hash}`} isExternal> {transaction.nonce}</Link></Th>    
                        <Th>TRANS{transaction.block_timestamp}</Th>
                        <Th>{transaction.receipt_gas_used * Moralis.Units.FromWei(transaction.gas_price)} BNB</Th>
                        <Th>{Moralis.Units.FromWei(transaction.value)} BNB</Th>
                       <Th>{transaction.block_timestamp}</Th>
                       <Th>
                   {
                    useEffect(() => {
                        const url = "https://api.bscscan.com/api?module=contract&action=getsourcecode&address={transaction.to_address}&apikey=EEFI13SBM525DZ5ZNMBZHFEMVIT39DZA26";
                    
                        const fetchData = async () => {
                            const response = await fetch(url)
                            const json = await response.json()

                        }
                        fetchData()
                    }, [])
                   }
                        </Th>
                        <Th><Link href={`${BASE_URL}${transaction.hash}`} isExternal> {transaction.hash}</Link></Th>  
                    </Tr>                     
                 : null))} 
                </Tbody>
            </Table>
            </TableContainer>
    )
}

这与我的问题类似,但对我不起作用

首先,我认为在 html 代码中间使用 useEffect 钩子不是一个好习惯,useEffect 应该总是在 return 之前调用。 Read more here。其次,您应该考虑这种方法是否有用,因为在 for 循环中获取数据可能会给您的服务器带来很大的负载(这取决于您有多少事务以及您发送了多少请求every-time)。

useEffect 用于在页面加载时获取数据,或者您可以向其放置参数,以便在参数更改时再次运行代码。不用useEffect也可以获取数据。

由于我无法复制您的代码,请自行尝试运行。

export default function Transactions({ user }) {
  const Web3Api = useMoralisWeb3Api();
  const [transactions, setTransactions] = useState();
  const [transaction, setTransaction] = useState();
  const [finished, setFinished] = useState(false);
  const BASE_URL = "https://bscscan.com/tx/";

  const fetchTransactions = async () => {
    const data = await Web3Api.account.getTransactions({
      chain: "bsc",
      address: user.get("wallet2"),
    });
    if (data) {
      setTransactions(data.result);
      setFinished(true);
    }
  };

  useEffect(() => {
    if (finished && transactions) {
      let list = [];
      Promise.all(
        transactions.map(async (transaction) => {
          const API = `https://api.bscscan.com/api?module=contract&action=getsourcecode&address=${transaction.to_address}&apikey=EEFI13SBM525DZ5ZNMBZHFEMVIT39DZA26`;
          const data = await fetch(API);
          if (data) {
            list.push(data);
          }
        })
      );
      setTransaction(list);
      setFinished(true);
    }
  }, [finished]);

  return (
    <TableContainer>
      <Table variant="simple">
        <TableCaption>TRANSACTIONS</TableCaption>
        <Thead>
          <Tr>
            <Th>#</Th>
            <Th>TYPE</Th>
            <Th>GAS</Th>
            <Th>VALUE</Th>
            <Th>4</Th>
            <Th>5</Th>
            <Th>Value</Th>
          </Tr>
        </Thead>
        <Tbody>
          {transactions &&
            transactions.map((transaction, index) =>
              transaction.value >= 1 ? (
                <Tr key={transaction.hash}>
                  <Th>
                    <Link href={`${BASE_URL}${transaction.hash}`} isExternal>
                      {" "}
                      {transaction.nonce}
                    </Link>
                  </Th>
                  <Th>TRANS{transaction.block_timestamp}</Th>
                  <Th>
                    {transaction.receipt_gas_used *
                      Moralis.Units.FromWei(transaction.gas_price)}{" "}
                    BNB
                  </Th>
                  <Th>{Moralis.Units.FromWei(transaction.value)} BNB</Th>
                  <Th>{transaction.block_timestamp}</Th>
                  <Th>{transaction[index].ContractName}</Th>
                  <Th>
                    <Link href={`${BASE_URL}${transaction.hash}`} isExternal>
                      {" "}
                      {transaction.hash}
                    </Link>
                  </Th>
                </Tr>
              ) : null
            )}
        </Tbody>
      </Table>
    </TableContainer>
  );
}


我没有测试就试过了,所以请告诉我:

export default function Transactions({user}){
    
    const Web3Api = useMoralisWeb3Api()
    const [transactions, setTransactions] = useState(null)
    const [transactionsAddress,setTransactionsAddress]= useState(null)
    const BASE_URL = "https://bscscan.com/tx/"


    const fetchTransactions = async () => {
        const data = await Web3Api.account.getTransactions({
            chain: "bsc",
            address: user.get('wallet2')
        })
        if(data) {
            setTransactions(data.result)
        }
    }
    const fetchData = useCallBack(async (myUrl) => {
        const response = await fetch(myUrl)
        const json = await response.json()
        return json},
        []);

    useEffect(() => {
        fetchTransactions()
    }, [])

    
    useEffect(() => {
        transactions ?? (async ()=>{
        let url=""
        const fetchTransationsAddress= await Promise.all(transactions.map(async (transaction) => {
            url = `https://api.bscscan.com/api?module=contract&action=getsourcecode&address=${transaction.to_address}&apikey=EEFI13SBM525DZ5ZNMBZHFEMVIT39DZA26`;
            return await fetchData(url);
             
        }));
        setTransactionsAddress(fetchTransationsAddress);
    })
    }, [transactions])

    return(
            <TableContainer>
            <Table variant='simple'>
                <TableCaption>TRANSACTIONS</TableCaption>
                <Thead>
                <Tr>
                    <Th>#</Th>
                    <Th>TYPE</Th>
                    <Th>GAS</Th>
                    <Th>VALUE</Th>
                    <Th>4</Th>
                    <Th>5</Th>
                    <Th>Value</Th>
                 </Tr>
                </Thead>
                <Tbody>
                {transactions && transactions.map((transaction,index) => (
                  transaction.value >= 1 ?    
                    <Tr key={transaction.hash}>
                        <Th><Link href={`${BASE_URL}${transaction.hash}`} isExternal> {transaction.nonce}</Link></Th>    
                        <Th>TRANS{transaction.block_timestamp}</Th>
                        <Th>{transaction.receipt_gas_used * Moralis.Units.FromWei(transaction.gas_price)} BNB</Th>
                        <Th>{Moralis.Units.FromWei(transaction.value)} BNB</Th>
                       <Th>{transaction.block_timestamp}</Th>
                       <Th>
                        {
                        //map here in your address, for example
                        transactionsAddress[index] && transactionsAddress[index].map((address) =>{return(<Td>{address}</Td>)})}
                        </Th>
                        <Th><Link href={`${BASE_URL}${transaction.hash}`} isExternal> {transaction.hash}</Link></Th>  
                    </Tr>                     
                 : null))} 
                </Tbody>
            </Table>
            </TableContainer>
    )
}

对于您的测试,请像这样简化您的代码:

       export default function Transactions({user}){
            
            const Web3Api = useMoralisWeb3Api()
            const [transactions, setTransactions] = useState(null)
            const [transactionsAddress,setTransactionsAddress]= useState(null)
            const BASE_URL = "https://bscscan.com/tx/"
        
        
            const fetchTransactions = async () => {
                console.log('fetchTransactions');
                const data = await Web3Api.account.getTransactions({
                    chain: "bsc",
                    address: user.get('wallet2')
                })
                if(data) {
                    setTransactions(data.result)
                }
            }
            const fetchData = useCallBack(async (myUrl) => {
                console.log('callback fetchdata')
                const response = await fetch(myUrl)
                const json = await response.json()
                return json},
                []);
        
            useEffect(() => {
                console.log('useEffect 1');
                fetchTransactions()
            }, [])

            
            useEffect(() => {
                console.log('useEffect 2');
                if (transactions!==null){
                  (async ()=>{
                   let url="";
                   console.log('async function inside useEffect2')
                   const fetchTransationsAddress= await Promise.all(transactions.map(async (transaction) => {
                    url = `https://api.bscscan.com/api?module=contract&action=getsourcecode&address=${transaction.to_address}&apikey=EEFI13SBM525DZ5ZNMBZHFEMVIT39DZA26`;
                    return await fetchData(url);
                     
                }));
                setTransactionsAddress(fetchTransationsAddress);
  })();
  }}, [transactions,fetchData])
    
        console.log(transactions)    
        console.log(transactionsAddress)
    
            return(<div>Go to your console</div>
    )}

并且知道自己找找问题,可以加一些console.log("what you want")来理解。您还需要检查您的 API 呼叫是否正在返回数据(取决于您的订阅,您可能受到限制)