Home > other >  Getting wrong data stored in state variable when the correct data is being console logged
Getting wrong data stored in state variable when the correct data is being console logged

Time:01-16

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:

  1. 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.

  2. You're missing the [] in setCoinIds(...coinIds, res.id), so what you're doing is spreading out the value of coinIds as discrete arguments to setCoinIds. But setCoinIds will ignore all but the first argument.

  3. 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 that coinIds may well be out of date by the time you do that. Instead, use the callback form of setCoinIds.

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 the id 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.
  •  Tags:  
  • Related