Hey @nadtn
Check your cloud function, it doesnāt return ETH balance - thatās why it shows NaN
.
The repo you shared doesnāt have Transactions.jsx
and works without any bugs.
Hey @nadtn
Check your cloud function, it doesnāt return ETH balance - thatās why it shows NaN
.
The repo you shared doesnāt have Transactions.jsx
and works without any bugs.
In the repo wasnāt updated (that was the last working version), can you please check now?
Canāt test since I have errors but changed:
const balQuery = new Moralis.Query("_EthAddress");
balQuery.equalTo("objectId", userAddress);
const balResult = await balQuery.first({useMasterKey: true});
results.push({
name: "Ethereum",
symbol: "ETH",
balance: balResult.get("EthBalance"),
decimals: 18
});
To
const balQuery = new Moralis.Query("EthAddress");
balQuery.equalTo("address", userAddress);
const balResult = await balQuery.first({useMasterKey: true});
results.push({
name: "Ethereum",
symbol: "ETH",
balance: balResult.get("balance"),
decimals: 18
});
Saved in the cloud functions section in the server, I donāt know when itāll be updated in my project or do I have to do it manually?
What I changed in the cloud function created an error. Iāll let you check first with the old one then Iāll look into the new one
The component name should match the name of the exported function:
You need to use:
export default function Transactions(date)
Instead of:
export default async function setDivDate(date)
Itās a bad practise to return async component like you did. All async logic should be outside component fucntion .
I suggest you to use accredited names for useState()
hooks:
Correct:
const [name,setName] = useState()
const [date, setDate] = useState();
Not Correct:
const [valueDate, onChange] = useState();
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
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
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.
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:
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.
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>);
}
}