Errors Unhandled Rejection & Objects are not valid as a React child

I spent a very long time working on your code, but it has a lot of errors. I suggest you learn React with something simpler. Make a to-do for example.

Just spend a couple of days studying the React itself :man_factory_worker:

Your cloud fucntion should be like:

// this goes in the Moralis server Cloud Functions section
Moralis.Cloud.define("getTokens", async(request) => {
  const {userAddress} = request.params;
  if (!userAddress){
    return [];
  }
  
  const tokenQuery = new Moralis.Query("EthTokenBalance");
  tokenQuery.equalTo("address", userAddress);
  const tokenResult = await tokenQuery.find();
  
  const results = tokenResult.map((token) => token.attributes);
  
  const balQuery = new Moralis.Query("EthBalance");
  balQuery.equalTo("address", userAddress);
  const balResult = await balQuery.first({useMasterKey: true});

  results.push({
    name: "Ethereum",
    symbol: "ETH",
    balance: balResult.get("balance"),
    decimals: 18
  });
  
  return results;
});

You need to query the EthBalance table isntead of _EthAddress

Ok I took into consideration your remarks, this is the new Transaction.jsx

import React, { useEffect, useState } from "react";
import pageflip from "../data/pageflip.mp3";
import { Moralis } from "moralis";

async function getTransactions (date) {

    console.log("date in getTransactions: " + date)
    // set lessThan date
    let nextDate = new Date(date);
    nextDate.setDate(nextDate.getDate()+1);
                
    let query = new Moralis.Query('EthTransactions')
    query.greaterThan("block_timestamp", date);
    query.lessThan("block_timestamp", nextDate);
    const resultDateTransaction = await query.find()

    return resultDateTransaction;
  }

function millisecondsToTime (ms) {
    let minutes = Math.floor(ms / (1000 * 60));
    let hours = Math.floor(ms / (1000 * 60 * 60));
    let days = Math.floor(ms / (1000 * 60 * 60 * 24));
    
    if (days < 1) {
        if (hours < 1) {
            if (minutes < 1) {
                return `less than a minute ago`
            } else return `${minutes} minutes(s) ago`
        } else return `${hours} hours(s) ago`
    } else return `${days} days(s) ago`
  }

  const pageflipAudio = new Audio(pageflip);
  const playSound = audioFile => {
    audioFile.play();
}


export default function Transactions ({date}) {


    const resultDateTransaction = getTransactions (date);

    if (resultDateTransaction.length > 0) {

    return (
      <table border = "1" bordercolor = "blue">
      <caption>${resultDateTransaction.length} transaction(s) ${date.toLocaleDateString()}</caption>
      <thead>
      <tr>
      <th scope="col">Transaction</th>
      <th scope="col">Block Number</th>
      <th scope="col">Age</th>
      <th scope="col">Type</th>
      <th scope="col">Fee</th>
      <th scope="col">Value</th>
      <th scope="col">Notes</th>
          </tr>
      </thead>
      <tbody>
      {resultDateTransaction.forEach((t) => {
    return (
    <tr>
        <td><a href='https://etherscan.io/tx/${t.attributes.hash}' target="_blank" rel="noopener noreferrer">${t.attributes.hash}</a></td>
        <td><a href='https://etherscan.io/block/${t.attributes.block_number}' target="_blank" rel="noopener noreferrer">${t.attributes.block_number}</a></td>
        <td>${millisecondsToTime(Date.parse(new Date()) - Date.parse(t.attributes.block_timestamp))}</td>
        <td>${t.attributes.from_address == Moralis.User.current().get('ethAddress') ? 'Outgoing' : 'Incoming'}</td>
        <td>${((t.attributes.gas * t.attributes.gas_price) / 1e18).toFixed(5)} ETH</td>
        <td>${(t.attributes.value / 1e18).toFixed(5)} ETH</td>
        <td><input type="text" id="name" name="name"></input><button>Save</button></td>
    </tr>
    );
})}
      </tbody>
      </table>
    );

    playSound(pageflipAudio);

}
}

Works fine I guess.
But I still get


I’ve also changed the cloud function like you said (the same as I suggested).
I don’t get why the errors says Transactions and points to coinData… Is a default needed for Transactions?

But yes it’s my first time using React, thought I would learn while building but I’ll definitely go back to the basics after the ETHOnline ends. I’m also thinking of integrating the academy. :wink:

I guess this happens because of this:
if (resultDateTransaction.length > 0) { }
You always need to return something for render from the component.

So make something like:

export default function Transactions({ date }) {
        if (resultDateTransaction.length > 0) {
          return <>Your code</>;
        } else {
          return <>Loading</>;
        }
      }

The default I was mentioning, I get it, it works.
But now that I have my async logic outside the component:

export default function Transactions ({date}) {


    const resultDateTransaction = getTransactions (date);
    console.log("Transactions: " + resultDateTransaction)
    console.log("Transactions lengh: " + resultDateTransaction.length)
    
    if (resultDateTransaction.length > 0) {

I have this result:
Transactions: [object Promise]
Transactions lengh: undefined

But inside getTransactions I have:
Transactions in getTransactions: [object Object],[object Object]

Why am I not having the same value? Promise is for async right?

const resultDateTransaction = await query.find()


    if (resultDateTransaction.length > 0) {

You are trying to get length of the promise

I suggest you to create new hook for the query. As an example you can use useCoinData

So the logic will be quite simple. If it is fetching you return [] when it is fetched you return an array with objects

I didn’t get it, can you elaborate?
Tried like you said

export default function Transactions ({date}) {


    const resultDateTransaction = useTransactionsData (date);
    console.log("Transactions: " + resultDateTransaction)
    console.log("Transactions lengh: " + resultDateTransaction.length)

And this is transactionsData.js


import { Moralis } from "moralis";

export const useTransactionsData = (date) => {

    console.log("date in getTransactions: " + date)
    // set lessThan date
    let nextDate = new Date(date);
    nextDate.setDate(nextDate.getDate()+1);
                
    let query = new Moralis.Query('EthTransactions')
    query.greaterThan("block_timestamp", date);
    query.lessThan("block_timestamp", nextDate);
    const resultDateTransaction = query.find()

    console.log("Transactions in get: " + resultDateTransaction)

    return resultDateTransaction;
  };

With same result:

just noticed this:

=>
const resultDateTransaction = await query.find()

True thanks CK!
Because I had this I removed it:


Tried to add async but didn’t work. Not used to it to tell you the truth.

You can find an example with async await here: React Error: You need to call Parse.initialize before using Parse

Thanks so here we go:

import { Moralis } from "moralis";

export const useTransactionsData = async (date) => {

    // set lessThan date
    let nextDate = new Date(date);
    nextDate.setDate(nextDate.getDate()+1);
                
    let query = new Moralis.Query('EthTransactions')
    query.greaterThan("block_timestamp", date);
    query.lessThan("block_timestamp", nextDate);
    const resultDateTransaction = await query.find()

    console.log("Transactions in get: " + resultDateTransaction)

    return resultDateTransaction;
  };

But I still get [object Promise] in resultDateTransaction

export default function Transactions ({date}) {


    const resultDateTransaction = useTransactionsData (date);
    console.log("Transactions: " + resultDateTransaction)
    console.log("Transactions lengh: " + resultDateTransaction.length)

When I have [object Object],[object Object] with resultDateTransaction
Guess I’m not using the hook the right way…

HI @nadtn,

It looks like you are not even using Moralis hooks anyway.

Please check out the hooks section to see how to use them. Hooks start with the key word “use”.

If you have a promise, you could still get its result using something like

resultDateTransaction.then(
    function(value) {console.log(value);},
    function(error) {console.log(error);}
  );

When in react, sometimes you could use console.log(JSON.stringify(object_)) so that you can see what is there instead of [object Object]

Thanks guys, Moralis hooks are so useful and it’s easier when can check the value of [object Object].
Hope this is correct, I just can’t see the content in tbody but thead and everything else is there.


I only have Transactions.jsx now

import pageflip from "../data/pageflip.mp3";

import { Typography } from "@material-ui/core";

import { Moralis } from "moralis";

import { useMoralisQuery } from "react-moralis";


function millisecondsToTime (ms) {
    let minutes = Math.floor(ms / (1000 * 60));
    let hours = Math.floor(ms / (1000 * 60 * 60));
    let days = Math.floor(ms / (1000 * 60 * 60 * 24));
    
    if (days < 1) {
        if (hours < 1) {
            if (minutes < 1) {
                return `less than a minute ago`
            } else return `${minutes} minutes(s) ago`
        } else return `${hours} hours(s) ago`
    } else return `${days} days(s) ago`
  }

  const pageflipAudio = new Audio(pageflip);
  const playSound = audioFile => {
    audioFile.play();
}


export default function Transactions ({date}) {

    playSound(pageflipAudio);

        // set lessThan date
        let nextDate = new Date(date);
        nextDate.setDate(nextDate.getDate()+1);
              
        const { data, error, isLoading } = useMoralisQuery("EthTransactions", query =>
        query
          .greaterThan("block_timestamp", date)
          .lessThan("block_timestamp", nextDate),
          [date],
      );
      
    //console.log("Transactions json: " + JSON.stringify(data, null, 2))
    
    if (!error & data.length > 0) {

    return (
      <table border = "1" bordercolor = "blue">
      <caption>{data.length} transaction(s) {date.toLocaleDateString()}</caption>
      <thead>
      <tr>
      <th scope="col">Transaction</th>
      <th scope="col">Block Number</th>
      <th scope="col">Age</th>
      <th scope="col">Type</th>
      <th scope="col">Fee</th>
      <th scope="col">Value</th>
      <th scope="col">Notes</th>
          </tr>
      </thead>
      <tbody>
      {data.forEach((t) => {
          console.log("hash" + t.attributes.hash)
          return(
    <tr>
        <td><a href='https://etherscan.io/tx/${t.attributes.hash}' target="_blank" rel="noopener noreferrer">{t.attributes.hash}</a></td>
        <td><a href='https://etherscan.io/block/${t.attributes.block_number}' target="_blank" rel="noopener noreferrer">{t.attributes.block_number}</a></td>
        <td>{millisecondsToTime(Date.parse(new Date()) - Date.parse(t.attributes.block_timestamp))}</td>
        <td>{t.attributes.from_address == Moralis.User.current().get('ethAddress') ? 'Outgoing' : 'Incoming'}</td>
        <td>{((t.attributes.gas * t.attributes.gas_price) / 1e18).toFixed(5)} ETH</td>
        <td>{(t.attributes.value / 1e18).toFixed(5)} ETH</td>
        <td><input type="text" id="name" name="name"></input><button>Save</button></td>
    </tr>
      ); })}
      </tbody>
      </table>
    );

}
else {
    return (<Typography>No transactions</Typography>);
}
}

does this console.log show what you expect?

It does!
hash0xa37fe8cf2a6c655a532e301634ab7cf771007f1b8cd4ec2703fb73785a1e7ca8
But what’s also weird is that we have 2 transactions and in the log it’s displayed twice.

Solved! New issue is already on a new topic

1 Like