2

I'm writing a React App that gets JSON data from an API and shows some of it's contents.

This is the data it gets:

{"id":6,"name":"5 Storey I=0.7","Value":1344981250,"NSt":5,"jRatio":"[0.2,0.4,0.4]","jEDR":"[0.02,0.1,0.5,1]"}

And this is the App:

class App extends React.Component{
    constructor(props){
        super(props);
        this.state={
            data: [],
            isLoading: false,
            error: null,
        };
    }
    componentDidMount(){
        this.setState({isLoading: true});
        axios.get(API)
            .then(response => console.log(response.data.Value))
            .then(response => this.setState({data: response.data, isLoading: false}))
            .catch(response => this.setState({error: response.error, isLoading: false}));
    }
    render(){
        return (
            <div>
            <p>{this.state.error}</p>
            <p>{this.state.isLoading ? 'Loading...':'Loaded'}</p>
            <ul>{this.state.data.Value.toString()}</ul>
            </div>
        )
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

I get the Value "1344981250" in console but the page throws this error:

TypeError: this.state.data.Value is undefined

and in console:

The development server has disconnected. Refresh the page if necessary.

I also tried this:

this.state.data.map(obj => <li key={obj.toString()}>{obj.toString()}</li>)

and this time without any error, nothing shows up on the page. (this one works for arrays of objects but shows nothing when it's just one object)

So what did I miss?

1
  • 1
    My guess is that in your second .then(response the response is undefined, since that's what console.log() "returns". Commented Jul 18, 2018 at 9:26

1 Answer 1

2

TypeError: this.state.data.Value is undefined

Because data is an array and [].Value (any key) will be undefined.

Check this snippet:

let data = [];

console.log('data.Value = ', data.Value);

// this will throw error:
console.log('data.value.toString', data.Value.toString())


You defined the initial value of data as an array, and you are getting the object from api call. Solution is define the initial value as:

data: {}

And inside render method, write it like this:

<ul>{(this.state.data.Value || '').toString()}</ul>

You need to return the response from .then:

axios.get(API)
  .then(response => {console.log(response.data.Value); return response;}   //<=== here
  .then(response => this.setState({data: response.data, isLoading: false}))
  .catch(response => this.setState({error: response.error, isLoading: false}))

Edit:

componentDidMount will get called after the initial rendering, so its better to define the initial value of isLoading: true, after that you can remove this:

this.setState({isLoading: true});
Sign up to request clarification or add additional context in comments.

4 Comments

And isLoading should start out as true, not just because this.setState() is asynchronous.
@ChrisG nice catch thanks, will add that in answer :)
Thanks for the answer! Problem fixed! But 1-why do I need to return the response?! And 2-I still have the error "server has disconnected" in console for this app, could it be from this code?
@Ehsan 1- because you are doing setState in 2nd .then, so if you don't return from 1st it will not be available in 2nd another option is do setState in 1st .then itself. 2- not sure about that error, can you share the full error message?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.