1

i got an array from server. here is the array:

[{"body":"one"},{"body":"two"},{"body":"three"}]

in Home2 component:

import React, { Component } from 'react';

class Home2 extends Component {
    constructor() {
        super()
        this.state={
            status:''
        }
    }
    componentDidMount(){
        let store = JSON.parse(localStorage.getItem('login'))
        var url = 'http://127.0.0.1:8000/myapi/allpost/?format=json'
        fetch(url,{
            method:'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Token '+store.token
            }
        })
        .then(res=>res.json().then(result=>{
            this.setState({status: result})
        }))
    }
    render() {
        var list = this.state.status
        var object = list[0]
        console.log(object['body'])// <-- what is the problem?
        return (
            <div>
                <h1>Hello</h1>
            </div>
        );
    }
}

export default Home2;

when the code run, it shows TypeError: undefined is not an object (evaluating 'object['body']')

where is the problem? how to console.log 'one' ?

Asif Biswas
  • 161
  • 2
  • 9
  • When you console.log(object) what does it log? If it logs {"body":"one"} then you can just call object.body. But I think it will log undefined – Sinan Yaman Dec 12 '20 at 15:48
  • 1
    n.b: `render` is called *before* `componentDidMount` (see: https://reactjs.org/docs/react-component.html#mounting) – ouroboring Dec 12 '20 at 15:49

2 Answers2

3

As people pointed out in the comments, an initial render is done before componentDidMount, so that's the reason why you're getting the error

To overcome that, you could return some default value (i.e Loading... div) in case this.state.status has not received the response yet:

render() {
    var list = this.state.status
    var object = list[0]
    if (!object) {
      return (
        <div>
          Loading...
        </div>
      )
    }
    console.log(object['body'])// <-- what is the problem?
    return (
        <div>
            <h1>Hello</h1>
        </div>
    );
}

I also found this interesting answer explaining more about the initial render and React's lifecycle: https://stackoverflow.com/a/45343644/5745962

Turtlean
  • 579
  • 4
  • 9
1

Your render method is called before componentDidMount method. Therefore you need to check if your object exists before you try to access a property of his.

also, you need to decide what kind of value you want to set in the status (it's a string or an array? from your code it seems like it should be an array of objects )

try to do it like this:

import React, { Component } from 'react';

class Home2 extends Component {
    constructor() {
        super()
        this.state={
            status:[]
        }
    }
    componentDidMount(){
        let store = JSON.parse(localStorage.getItem('login'))
        var url = 'http://127.0.0.1:8000/myapi/allpost/?format=json'
        fetch(url,{
            method:'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Token '+store.token
            }
        })
        .then(res=>res.json().then(result=>{
            this.setState({status: result})
        }))
    }
    render() {
        if(this.state.status.length){
        var list = this.state.status
        var object = list[0]
        console.log(object['body'])// <-- what is the problem?
        return (
            <div>
                <h1>Hello</h1>
            </div>
        );
        }
        else {
          return null; //or return in here some kind of loader
        }
    }
}

export default Home2;
Ran Marciano
  • 1,431
  • 5
  • 13
  • 30