1

The general outline of the React Component is as follows:

const API = 'https://min-api.cryptocompare.com/data/histohour?fsym=BTC&tsym=USD&aggregrate=168&limit=168&api_key=90f934173fe9dd81d5acc53f0a9a6c56a9ffcce322e24e722fa842deeff3601b'

class BtcOverview extends React.Component {
  constructor(props) {
    super(props);
        ...
    this.intPriceData = [];
  }

 componentWillMount() {

    fetch(API)
    .then(results => results.json())
    .then(marketData => {

      var count = 0;
      for (let number in marketData.Data){
        this.intPriceData.push(marketData.Data[number].close)
      };

    })
  }

When this.intPriceDash is accessed outside of Fetch() it returns an array of objects, a snippet of which can been seen in the pic below:

Console output for this.intPriceData

I need a standard Array like this [1,4,6] from the array of objects, however it will not respond to any Object operators I try such as Object.value() and will always return undefined.

I have no idea how to get the values that I need from it and whether there is some issue with the data type.

I can't work with the API data within the Fetch() method as perhaps would be the standard because the code I am working with does not easily accommodate that, hence me trying to access it elsewhere.

Any ideas would be really appreciated. T

phoenixson
  • 117
  • 10
  • 2
    It's already an array, as far as I can tell. Just use this: `this.intPriceData = marketData.Data.map(obj => obj.close);` –  Jan 31 '19 at 22:29
  • how is it not a standard array? – epascarello Jan 31 '19 at 22:32
  • It doesn't respond to Object.values(). It returns 'undefined'. – phoenixson Jan 31 '19 at 22:38
  • 1
    Please show where you're calling `Object.values()`. Calling it on an array just returns the array, so it should "work". If you're getting undefined, something else is wrong. Show the relevant code. –  Jan 31 '19 at 22:39
  • Are you reading it before it is returned? Basically you ordered a pizza and you are trying to eat the pizza before it gets to your house. You probably should be setting state and it will render when it is updated. – epascarello Jan 31 '19 at 22:46
  • Where are you logging the array? Or trying to access what it contains? Because `fetch()` is asynchronous, so my suspicion is that you're doing it before it contains values. console output is live though, so the output will update when the array populates. –  Jan 31 '19 at 22:46
  • https://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about-evaluating-arrays – epascarello Jan 31 '19 at 22:52
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) –  Jan 31 '19 at 22:55

4 Answers4

0

I don't think this is an array of objects. It is just how dev tools fold arrays to not show you all items at once.

Run this snippet in console: let a = []; for(let i = 0; i < 200; i++) a.push(1);

This will generate array with 200 elements inside. Then, see how it will be displayed in console.

Piotr Szlagura
  • 650
  • 5
  • 15
  • It shows like this - > 'Array(200) [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, … ]' before I click on it. Which to me outlines that things are 'normal'. The output I am getting from my 'this.intPriceData' first shows as 'Array []' . It doesn't show the number of items in the array or some of the first few values as might be the norm. – phoenixson Jan 31 '19 at 22:44
0

Looks like the response data is already in the correct format. Consider using the Array#map() method to transform it to an array of values for the close field that exists on each item of the marketData.Data array:

const API = 'https://min-api.cryptocompare.com/data/histohour?fsym=BTC&tsym=USD&aggregrate=168&limit=168&api_key=90f934173fe9dd81d5acc53f0a9a6c56a9ffcce322e24e722fa842deeff3601b'

var intPriceData = [];

fetch(API)
  .then(results => results.json())
  .then(marketData => {

    intPriceData = marketData.Data.map(item => item.close);

    console.log(intPriceData);
  })

Update

Seeing that you are working with ReactJS, here is an example integration showing how the close data could be rendered in your component after it is returned from fetch():

class BtcOverview extends React.Component {
  constructor(props) {
    super(props);

    // Initial state
    this.state = { intPriceData : [] };
  }

 componentWillMount() {

    fetch(API)
    .then(results => results.json())
    .then(marketData => {

        // Update state of component
        this.setState({ 
          intPriceData : marketData.Data.map(item => item.close) 
        });

    })
  }

  render() { 
     return (<ul>{ this.state.intPriceData.map(close => <li>{close}</li>)}</ul>)
  } 
}
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • The change you suggested generated this : '[] ​ length: 0 ​ : Array [] ' – phoenixson Jan 31 '19 at 22:49
  • I should stress that Inside the Fetch(). The data output is fine. Trying to access this.intPriceData outside of the Fetch().then() is what generates the outline of an object which I showed in the picture. – phoenixson Jan 31 '19 at 22:50
  • Hi Danny it works as mine did before albeit you code is certainly more high performance than mine. But as with mine when I tried to access this.intPriceData from outside of the Fetch() method then I am unable to work with the object that get thrown out. – phoenixson Jan 31 '19 at 22:53
  • My issue still remains. When accessed outside of the Fetch() method the object is transformed somehow such that Object & Array methods don't work on it anymore. – phoenixson Jan 31 '19 at 22:57
  • It returned undefined for me. – phoenixson Jan 31 '19 at 23:12
  • What returned undefined? – Dacre Denny Jan 31 '19 at 23:13
0

I think you just need to map the array of objects to return only the value you need:

const API = 'https://min-api.cryptocompare.com/data/histohour?fsym=BTC&tsym=USD&aggregrate=168&limit=168&api_key=90f934173fe9dd81d5acc53f0a9a6c56a9ffcce322e24e722fa842deeff3601b'

fetch(API)
  .then(results => results.json())
  .then(marketData => {
    const intPriceData = marketData.Data.map(item => item.close);
    
    console.log(intPriceData);
  });
mab
  • 378
  • 1
  • 8
0

The issue you have is the fact that the fetch is asynchronous and what ever you are reading is happening before it is fully loaded. So what happens is that the componentWillMount is calling the pizza place and making the order. The render code (that is what I am assuming you are using it) is not waiting for the data to be loaded.

So what can you do? One option is to use state which than will render when the value changes.

class BtcOverview extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      intPriceData : []
    }
    this.API = 'https://min-api.cryptocompare.com/data/histohour?fsym=BTC&tsym=USD&aggregrate=168&limit=168&api_key=90f934173fe9dd81d5acc53f0a9a6c56a9ffcce322e24e722fa842deeff3601b'
  }

 componentWillMount() {
    fetch(this.API)
      .then(results => results.json())
      .then(({ Data }) => {
        const intPriceData = Data.map(itm => itm.close);
        this.setState({ intPriceData })
      })
  }

  render () {
    const { intPriceData } = this.state
    return (<p>{intPriceData.length}</p>)
  }
}
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • In the end I decided not to bother to move any of the raw data outside of the Fetch() method and that worked. It's not the best, elegant or even correct solution. But I will take it. – phoenixson Feb 03 '19 at 14:31