0

Im a beginner with react and I have tried to work with the fetch api. I want to fetch some data about population from an api. I have managed to retrieve the data but when i try to setState inside the fetch the charts doesn't update with the new array. Below is my code from the app.js, hope this is enough information:

class App extends Component {

  constructor(){
    super();
    this.state = {
      chartData:{}
    }
  }

  componentWillMount(){
    this.getChartData();
  }

  getChartData(){
    let queryPost = {
    "query": [
      {
        "code": "Region",
        "selection": {
          "filter": "vs:RegionLän07",
          "values": [
            "01"
          ]
        }
      },
      {
        "code": "ContentsCode",
        "selection": {
          "filter": "item",
          "values": [
            "BE0101N1"
          ]
        }
      }
    ],
    "response": {
      "format": "json"
    }
    }

    fetch('https://api.scb.se/OV0104/v1/doris/sv/ssd/START/BE/BE0101/BE0101A/BefolkningNy'
    ,{
    method:'post',
    body:JSON.stringify(queryPost),
    })

    .then(response => response.json())
    .then(result => result.data.map(obj => (
    parseInt(obj.values[0])
    )))
    .then(newArr => this.setState({chartData:{
      labels:['dsa','cava','daba','baba'],
      datasets:[
        {
        label:'Populations',
        data: [newArr[0],newArr[1],newArr[2]],
        backgroundColor:[
            'rgba(255,99,132,0.6)',
            'rgba(100,100,2,0.6)',
            'rgba(10,100,2,0.6)',
        ],
        }
      ]
    }},console.log(this.state.chartData))
    )}   

  render(){
    return (
    <div className="content">
      <div className="row justify-content-center align-items-center header">
        <h1>Befolkningsinfo</h1>
      </div>
      <div className="row">
        <div className="col-md-6 col-sm-12">
          <div className="App">

          </div>
        </div>
        <div className="col-md-6 col-sm-12">
          <div className="App">
            <BarChart chartData={this.state.chartData} title='Chart1'/>
          </div>
        </div>
      </div>
      <div className="row">
        <div className="col-md-6 col-sm-12">
          <div className="App">

          </div>
        </div>
        <div className="col-md-6 col-sm-12">
          <div className="App">
            <PieChart chartData={this.state.chartData} title='Chart2'/>
          </div>
        </div>
      </div>
    </div>
    )
  }
}

export default App;
Richard L S
  • 33
  • 1
  • 3
  • 1
    How do you know it is not being set ? From the `console.log` ? If so then you should know that it is wrong. the second argument to `setState` must be a callback. so replace the `console.log(this.state.chartData)` with `()=>console.log(this.state.chartData)` – Gabriele Petrioli Mar 27 '19 at 21:46
  • Also looking at the `react-chartjs` docs i see that the expected prop for the data is named `data` and not `chartData` so you might want to also try `` – Gabriele Petrioli Mar 27 '19 at 21:50
  • @admcfajn Thanks, I tried but did not work :( – Richard L S Mar 27 '19 at 21:50
  • @GabrielePetrioli Thank you, you are right about the console.log it works! However still some issues getting the chart to work but I will sleep on it and try tomorrow. – Richard L S Mar 27 '19 at 22:04

1 Answers1

0

You want to call the fetch in componentDidMount. By the time componentDidMount is called, the component has been rendered once.

In practice, componentDidMount is the best place to put calls to fetch data, for two reasons: Using didMount makes it clear that data won’t be loaded until after the initial render. This reminds you to set up initial state properly, so you don’t end up with undefined state that causes errors.

If you ever need to render your app on the server, componentWillMount will actually be called twice – once on the server, and again on the client – which is probably not what you want. Putting your API call code in componentDidMount will ensure that data is only fetched from the client, where it should be.

bharney
  • 41
  • 1
  • 4
  • Thank you for the clarification, I tried use componentDidMount but it did not work either. Im probably doing something else wrong. – Richard L S Mar 28 '19 at 07:26