I am trying to store data in my state. When I console log the data I get the correct data. When I store it in my state and console log it, I keep getting "c" in my console. Why is C being stored in my state when there is no sign of "c" in my entire code
This keeps giving me C in my console.
const getIds = async () => {
Axios.get(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false"
).then((response) =>
response.data.map((res) => setCoinIds(...coinIds, res.id))
);
console.log(coinIds);
};
This logs the correct data:
const getIds = async () => {
Axios.get(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false"
).then((response) => response.data.map((res) => console.log(res.id)));
};
Why is the data not stored in my state?
CodePudding user response:
There are a few things going on:
You're looping over the received resources, but reusing the same
coinIds
every time; that will lose previous updates and only keep the last one.You're missing the
[]
insetCoinIds(...coinIds, res.id)
, so what you're doing is spreading out the value ofcoinIds
as discrete arguments tosetCoinIds
. ButsetCoinIds
will ignore all but the first argument.Separately from #1, you could well also be running into the "stale closure" problem. Your code is setting state based on existing state (by using
coinIds
when setting the new value). You're also doing asynchronous work, which means thatcoinIds
may well be out of date by the time you do that. Instead, use the callback form ofsetCoinIds
.
Separately, the console.log
at the end fo getId
will show you the value prior to the Axios callback, so it's not giving you any useful information and could be confusing.
Finally, there's no reason for getIds
to be async
. You're not using await
within it, you're using .then
instead. (It also needs a .catch
.)
Fixing those things:
const getIds = () => {
Axios.get(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false"
)
.then((response) => {
setCoinIds(coinIds => [...coinIds, ...response.data.map(res => res.id)])
})
.catch(error => {
// ...report/handle error...
});
};
That does this:
- Loops through
response.data
getting an array of theid
values of each of the data objects. - Makes only a single call to
setCoinIds
, filling in all the new values at once. - Uses
[]
so we're passing a single array. - Uses the callback form of
setCoinIds
so that it's using the most up-to-date state value.