2

So I have this react app made for a IoT project that as 3 charts with temperature and humity of soil and air, I make a fetch to my API witch returns a response JSON similar to this(But with 10 data values, I didn't include all to not make this post huge):

{
  "dados":[
{
  "T_air":20,
  "H_air":60,
  "soil":70,
  "Time":"2019-12-12T16:09:35.719Z"
},
{
  "T_air":20,
  "H_air":60,
  "soil":70,
  "Time":"2019-12-12T16:09:35.719Z"
},
{
  "T_air":20,
  "H_air":60,
  "soil":70,
  "Time":"2019-12-12T16:09:35.719Z"
},
{
  "T_air":20,
  "H_air":60,
  "soil":70,
  "Time":"2019-12-12T16:09:35.719Z"
},
{
  "T_air":20,
  "H_air":60,
  "soil":70,
  "Time":"2019-12-12T16:09:35.719Z"
}
],
  "LastTime":"12/12/2019, 15:43:53"
}

The point is I need to print the LastTime object in the render, for that I use the setState property but if console.log the ResData I can see my object, however if I console.log results It says undefined. You can see in my code that if I use ResData.dados[i].T_air it gives no problem at all, so It's not the API fault.

import React, { Component } from 'react';
import '../App1.css'
import CanvasJSReact from '../assets/canvasjs.react';
var CanvasJSChart = CanvasJSReact.CanvasJSChart;


var dataPoints =[];
var dataPoints_1 = [];
var dataPoints_2 = [];


class LineChart extends Component {
    constructor(props){
        super(props);
        this.state={
            results: []
        };
    }

.
.
.
.
componentDidMount(){
        var chart = this.chart;
        var chart1 = this.chart1;
        var chart2 = this.chart2;
        fetch('http://localhost:4000/espdata/')
        .then((response) => {
            return response.json();
        })
        .then((ResData) => {
            for (var i = 0; i < 10; i++) {
                var today = new Date(ResData.dados[i].Time);
                dataPoints.push({
                    x: today,
                    y: ResData.dados[i].T_air
                });
                dataPoints_1.push({
                    x: today,
                    y: ResData.dados[i].H_air
                });
                dataPoints_2.push({
                    x: today,
                    y: ResData.dados[i].soil
                });
            }
            chart.render();
            chart1.render();
            chart2.render();
            this.setState({results: ResData.LastTime});
            console.log(this.results);   //UNDEFINED
            console.log(ResData.LastTime) // "12/12/2019, 15:43:53"
        });
    }
.
.
.
.
PmmZenha
  • 155
  • 2
  • 9
  • 2
    It's normal this.results is undefined, this would be this.state.results. However, you can't access state directly after you've set it. – Axnyff Dec 12 '19 at 16:09
  • 1
    setState is async function – Belmin Bedak Dec 12 '19 at 16:11
  • 1
    What @Axnyff says is correct. Change it to use this.state.results and you will get an empty array instead of undefined. setState is asynchronous, so you can't access the results you want immediately. – Cal Irvine Dec 12 '19 at 16:11
  • 1
    1. You have to access results by `this.state.results`. Because we are setting results property inside the state object. 2. Basically setState is asynchronous, so if you try print in the next line it will return previous value(If no value initiated, then it will be undefined). So use callback function for further operation. It is very similar to Promise. – Srigar Dec 12 '19 at 16:17
  • 1
    @Axnyff thanks a lot it worked. I did

    {this.state.results}

    and it prints now the time! I feel dumb by not realising I had to use this.state. Thx a lot
    – PmmZenha Dec 12 '19 at 16:19
  • 1
    Another popular duplicate target: [Why calling react setState method doesn't mutate the state immediately?](https://stackoverflow.com/q/30782948/1218980) – Emile Bergeron Dec 12 '19 at 16:19
  • @Srigar Used the arrow function to console.log and worked. Now I understood better. Cheers mate – PmmZenha Dec 12 '19 at 16:21

1 Answers1

-2

SetState is A Promise, if you need to use it immediately after setting it, you should use it as a promise, like this:

this.setState({results: ResData.LastTime}, () => {console.log(this.state. results); })