Search code examples
reactjsfetchuse-effect

React function inside a fetching


I'm listing a table with lot of rows, and i would like to use a new function in each row dependly on the {transaction.to_address} value

I want to use useeffect() function inside a fetching function, but i've got this error message: Rendered more hooks than during the previous render. I have tried many solution i found here, i've spent almost a whole day, but i'm not smart enough to fix it.

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>
    )
}

This is similar to my problem, but not working for me

Uncaught Invariant Violation: Rendered more hooks than during the previous render


Solution

  • First of all i don't think it's a good practice to use useEffect hook in the middle of html code, useEffect should be always called before return. Read more here. Secondly you should think if this approach is any good as fetching data in a for cycle might cause much load on your server (it depends how many transactions you have and how many requests you are sending every-time).

    useEffect is used to fetch data when the page loads or you can place parameters to it so it runs the code again when the parameters change. You can fetch data without useEffect.

    As i cannot replicate your code please try running this on your own.

    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>
      );
    }