I have a situation that I can not solve for some reason.
Let me explain what I'm trying to do:
I am trying to get number of crypto tokens received by entering a contract and an address (which helps me to reach out the API results).
For the moment, it works like this: https://thecryptoguetter.netlify.app/pages/HowMuchGlobal
So as you can see, I ask the user to chose a network (because API endpoints are different but they are all structured the same way)
My goal: Allowing users to simply enter a contract and an address, and I'll manage to get the right answer on my side.
What do I need:
I need to make multiple requests and get the answer of the one which works. For that, this is quite easy on the paper, the message in the API is "OK" if it's ok, and "NOTOK" if not. Simple ahah
But for some reason, I'm drowning with the logic, and tried multiple things but my brain is bugging hard on this one.
Here is what I did:
import axios from "axios";
const HowMuchTest = () => {
const [tokenContract, setTokenContract] = useState("");
const [address, setAddress] = useState("");
const [answerAPI, setAnswerAPI] = useState([]);
const [total, setTotal] = useState([]);
const [decimals, setDecimals] = useState(18);
const [txDatasArray, setTxDatasArray] = useState();
const handleTokenContract = (event) => {
const searchTokenContract = event.target.value;
setTokenContract(searchTokenContract);
};
const handleAddress = (event) => {
const searchAddress = event.target.value;
setAddress(searchAddress);
};
const clearToken = () => {
setTokenContract("");
setAddress("");
setTotal([]);
};
useEffect(() => {
axios
.all([
axios.get(
`https://api.bscscan.com/api?module=account&action=tokentx&contractaddress=${tokenContract}&address=${address}&page=1&offset=100&startblock=0&endblock=27025780&sort=asc&apikey=[KEY]`
),
axios.get(
`https://api.etherscan.io/api?module=account&action=tokentx&contractaddress=${tokenContract}&address=${address}&page=1&offset=100&startblock=0&endblock=27025780&sort=asc&apikey=[KEY]`
),
])
.then(
axios.spread((...res) => {
setAnswerAPI(res);
})
);
}, [address, tokenContract]);
console.log(answerAPI[0].data);
useEffect(
(answerAPI) => {
if (answerAPI[0].data.message === "OK") {
setTxDatasArray(answerAPI[0]);
} else if (answerAPI[1].data.message === "OK") {
setTxDatasArray(answerAPI[1]);
}
},
[answerAPI]
);
console.log(txDatasArray);
useEffect(() => {
let dataArray = [];
for (let i = 0; i < answerAPI.length; i ) {
let toLower = answerAPI[i]?.to?.toLowerCase();
let addressLower = address?.toLowerCase();
if (toLower === addressLower) {
dataArray.push({
ticker: answerAPI[0].tokenSymbol,
value: Number(answerAPI[i].value),
});
}
}
setDecimals(Number(answerAPI[0]?.tokenDecimal));
setTotal(dataArray);
}, [address, answerAPI, decimals]);
const totaltotal = total.reduce((a, v) => (a = a v.value), 0);
const FinalTotal = () => {
if (decimals === 6) {
return (
<div>
{(totaltotal / 1000000).toFixed(2).toLocaleString()} {total[0].ticker}
</div>
);
} else if (decimals === 18) {
return (
<div>
{(totaltotal / 1000000000000000000).toFixed(2).toLocaleString()}{" "}
{total[0].ticker}
</div>
);
}
};
return (
<div className="how-much">
<div className="received-intro">
<h1>Find out how much did you receive on a particular token</h1>
</div>
<div className="token-contract">
<input
type="text"
placeholder="Token Contract Address"
value={tokenContract}
onChange={handleTokenContract}
/>
<input
type="text"
placeholder="ERC20 Address"
value={address}
onChange={handleAddress}
/>
</div>
{totaltotal !== 0 && (
<div className="show-total-received">
<div className="total-received">
<FinalTotal />
</div>
<div>{total.ticker}</div>
</div>
)}
<button className="btn btn-info" onClick={clearToken}>
Clear
</button>
</div>
);
};
export default HowMuchTest;
The part to look is the two first useEffect.
I get the following answer from the console: Cannot read properties of undefined (reading 'data')
Which is weird because I can reach answerAPI[0].data in the first console.log
So yes, I'm totally lost and can't figure it out. I tried a for loop in a useEffect too but it ended in an infinite loop...
Thank you in advance for the ones who will read until there!
Have a good day
CodePudding user response:
The problem is in your useEffect
implementation. The function passed to useEffect
does not take any arguments, so answerAPI
as written will always be undefined
, because inside this function it is the non-existing argument, and not your state as you might have expected.
You can change it to:
useEffect(() => {
if (answerAPI[0]?.data?.message === "OK") {
setTxDatasArray(answerAPI[0]);
} else if (answerAPI[1]?.data?.message === "OK") {
setTxDatasArray(answerAPI[1]);
}
}, [answerAPI]);