VnC
VnC

Reputation: 2016

JS state updates unexpectedly

I am very new to JS.

Here is a page that I am working on:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import Plot from 'react-plotly.js';
import { fetchPosts, createPost } from '../actions/postActions'

import GroupedBarChart from '../containers/GroupedBarChart'

class Usage extends Component {
    state = {
        title: '',
        resp_data: [],
    }

    componentDidMount() {
        this.props.fetchPosts('/en/api/usage/')
    }

    componentWillReceiveProps (nextProps) {
        if (nextProps.posts.data) {
            this.setState({resp_data: nextProps.posts.data}, function () {
                console.log(this.state.resp_data);
            });
        }
        console.log(this.state.resp_data)
    }

    render() {
        const { title, resp_data } = this.state

        return (<div>
            <GroupedBarChart
                title={ title }
                data={ resp_data }
            />
        </div>);
    }
}

const mapStateToProps = state => ({
    posts: state.posts.items,
    newPost: state.posts.item
})

export default connect(mapStateToProps, { fetchPosts, createPost })(Usage)

The problem with that is that the state changes unexpectedly at some point.

So in componentWillReceiveProps there is a console.log immediately after the setState call and the output of this console.log is exactly what I expect. However, if I print the state immediately after the if statement:

if (nextProps.posts.data) {
    this.setState({resp_data: nextProps.posts.data}, function () {
        console.log(this.state.resp_data);
    });
}

this.state.resp_data is an empty array.

The output of the two console.logs looks like that:

[] # this is outside if
(2) [{…}, {…}] # this is inside if

Can someone explain me why this happens and how can I overcome it?

Thanks in advance.

Upvotes: 0

Views: 48

Answers (2)

Poyraz Yilmaz
Poyraz Yilmaz

Reputation: 5857

First of get rid of componentWillReceiveProps method as it is not recommended to use anymore and it will be remove at version 17. You can check here for extra information.

Secondly checkout react lifecyles so you will see your component will render with initial data at mounting phase, so I assume you have no posts.data at first and you fetch it at componentDidMount. So after you fetched data you trigger setState which cause another render (check lifecycle updating phase you will see setState cause render).

You call console.log after calling setState and expecting to see some data but if you look at the documentation of it you will see it is not guarantee.

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.

Upvotes: 1

VnC
VnC

Reputation: 2016

For some reason when I changed the response in the back end - data = [] to data = {} it has worked. I am still confused of why would that be.

Upvotes: 0

Related Questions