最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Getting an error while trying to access nested objects in Reactjs - Stack Overflow

programmeradmin1浏览0评论

I am retrieving JSON data from an API and then storing it in state and when I try to access the data using this.state (eg i write this.state.DetailData.title) it works fine but when I try to access the nested data (eg this.state.DetailData.location.address) of the same object it throws me an error:

TypeError: Cannot read property 'address' of undefined

Here is my code:

import React from 'react'
import Caro from './Carousel'
import {
  Container,
  Row,
  Col
} from 'reactstrap';


class Detail extends React.Component {
  constructor(props)

  {
    super(props)
    this.state = {
      DetailData: []
    }

  }




  ponentDidMount() {

    fetch('', {
        method: 'GET'
      })
      .then((response) => response.json())
      .then((data) => {

        this.setState({
          DetailData: data.response
        })
        console.log(typeof(this.state.DetailData));

      })
  }




  render() {

    return ( 
    <div>

      <Caro / >

      <Container >
      <Row >
      <Col xs = "12" sm = {{size: 8, offset: 2 } md = {{size: 8, offset: 2}} >

      < div >
      <h1> {this.state.DetailData.title} <h1> 
      <h1> {this.state.DetailData.location.address} </h1>    {/*getting error here*/}
      <hr/>
      <h6> {this.state.DetailData.description} </h6>    

      </div>

      </Col>

      </Row> 
      </Container>

 
      </div>
    );



  }

}

export default Detail;

I am retrieving JSON data from an API and then storing it in state and when I try to access the data using this.state (eg i write this.state.DetailData.title) it works fine but when I try to access the nested data (eg this.state.DetailData.location.address) of the same object it throws me an error:

TypeError: Cannot read property 'address' of undefined

Here is my code:

import React from 'react'
import Caro from './Carousel'
import {
  Container,
  Row,
  Col
} from 'reactstrap';


class Detail extends React.Component {
  constructor(props)

  {
    super(props)
    this.state = {
      DetailData: []
    }

  }




  ponentDidMount() {

    fetch('https://api.kloh.in/kloh/external/v1/activity/AID180917200010526C8LFJ4MEIE9CWGXZG4', {
        method: 'GET'
      })
      .then((response) => response.json())
      .then((data) => {

        this.setState({
          DetailData: data.response
        })
        console.log(typeof(this.state.DetailData));

      })
  }




  render() {

    return ( 
    <div>

      <Caro / >

      <Container >
      <Row >
      <Col xs = "12" sm = {{size: 8, offset: 2 } md = {{size: 8, offset: 2}} >

      < div >
      <h1> {this.state.DetailData.title} <h1> 
      <h1> {this.state.DetailData.location.address} </h1>    {/*getting error here*/}
      <hr/>
      <h6> {this.state.DetailData.description} </h6>    

      </div>

      </Col>

      </Row> 
      </Container>

 
      </div>
    );



  }

}

export default Detail;

Share Improve this question edited Sep 20, 2018 at 13:43 Collin ter Steege 5235 silver badges17 bronze badges asked Sep 20, 2018 at 13:38 Hadi MirHadi Mir 5,1532 gold badges32 silver badges33 bronze badges 6
  • Can you do console.log(this.state.DetailData); and share the data – Hemadri Dasari Commented Sep 20, 2018 at 13:40
  • log the data to see if you are not misspelling something or even if the property location.address is exists or not ???? – amdev Commented Sep 20, 2018 at 13:42
  • The whole DetailData object is displayed – Hadi Mir Commented Sep 20, 2018 at 13:42
  • @hadi could you add the JSON or console output to the question please? – stef Commented Sep 20, 2018 at 13:45
  • You need to wait for the ponent to fetch data before using it in the render method. Try to add a flag variable isLoaded to state having default value set to false and then set it to true once the data is fetched in the ponentDidMount method and then conditionally render bases on that isLoaded . Read the link – Sumit Parkash Commented Sep 20, 2018 at 13:51
 |  Show 1 more ment

5 Answers 5

Reset to default 7

When the ponent is mounted your data are not yet fetched so the this.state.DetailData is an empty object and the this.state.DetailData.location is indeed undefined.

To solve this problem you can try checking if the object exists before displaying it. Something like this:

{this.state.DetailData.location ? this.state.DetailData.location.address : ""}

You should also check why you define the DetailData as an array when you initialise your ponent but seem to be expecting an object instead.

this.state = {
  DetailData: [] // this should be DetailData: {} or DetailData: null
}

Looking at https://api.kloh.in/kloh/external/v1/activity/AID180917200010526C8LFJ4MEIE9CWGXZG4, sometimes the location field there is null so you'll need to check for that.

For avoiding this scenario I would suggest you to use

https://lodash./docs/4.17.10#get 

it is a much cleaner way to get the value for deeply nested property. Install lodash and import it then use

import React from 'react'
import Caro from './Carousel'
import {
 Container,
 Row,
 Col
} from 'reactstrap';

import _ from 'lodash';

class Detail extends React.Component {
 constructor(props)

{
super(props)
this.state = {
  DetailData: []
}

}




ponentDidMount() {

fetch('https://api.kloh.in/kloh/external/v1/activity/AID180917200010526C8LFJ4MEIE9CWGXZG4', {
    method: 'GET'
  })
  .then((response) => response.json())
  .then((data) => {

    this.setState({
      DetailData: data.response
    })
    console.log(typeof(this.state.DetailData));

  })
}




render() {

return ( 
<div>

  <Caro / >

  <Container >
  <Row >
  <Col xs = "12" sm = {{size: 8, offset: 2 } md = {{size: 8, offset: 2}} >

  < div >
  <h1> {_.get(this.state, 'DetailData.title', 'any_default_value_for_title')} <h1> 
  <h1> {_.get(this.state, 'DetailData.location.address', 'any_default_value_for_address')} </h1>    {/*getting error here*/}
  <hr/>
  <h6> {_.get(this.state, 'DetailData.description', 'any_default_value_for_description')} </h6>    

  </div>

  </Col>

  </Row> 
  </Container>


  </div>
);



  }

  }

  export default Detail;

This is adding one more library to your project. But this is the clean way to do it.

Your render method is running before de ComponentDidMount function so the initial state is being used there, where the this.state.DetailedData is an empty array so this.state.DetailData.location is undefined and you can not check the this.state.DetailData.location.address without getting an error so you need to check whether it exists the location or not

using react,react-redux, useSelector

useSelector is the hooks alternative to mapstatetoprops

i found that i could not map nested object 'typeerror cannot read property of undefined'

my data looks like this

orderDetails:{loading:_, error:_, order:{etc:_,items:[...,{etc:_}]}

error

useEffect(()=>{...dispatch()},[])
const orderDetails = useSelector(state=>state.orderDetails)
const {order, loading, error}= orderDetails;

worked by using useSelector and selecting deeper state vs destructuring

const order = useSelector(state=>state.orderDetails.order)
发布评论

评论列表(0)

  1. 暂无评论