2

I am using axios to fetch data from api. My router is:

<Route exact path='/device/:id/update' render={(props) => <DeviceTypeUpdate {...props} />} />

My componentDidMount is :

componentDidMount() {
  console.log('------this.props.match.id----', this.props.match.params.id)
  const ied = this.props.match.params.id
  axios({
    url: 'http://127.0.0.1:8000/api/devicetypeget/'+ied,
    method: 'get',
    headers: {
      'Content-Type' : 'application/json'
    }
  })
  .then(function(response) {
    return response;
  })
  .then(function (devicetype) {
    this.setState(function () {
      return {devicetype: devicetype, isLoaded: true}
    })
  }.bind(this))
  .catch(function (error) {
    this.setState(function () {
      return {error, isLoaded: true}
    })
  }.bind(this))
}

In my render method, I tried to log data in console, as given below:

const {error, isLoaded, devicetype} = this.state
console.log('----error----', error);
console.log('----devicetype in render----', devicetype.data);

devicetype.data prints out the JSON object which has nested data in it as given below:

assignment_date: {$date: 1548744545634}
device_elements: {type: "switch", name: "board", state: "some state"}
dev_stage: "PLANNING"
type_description: "some description"
type_name: "Board"
_id: 1

when I console.log(devicetype.data.device_elements) or any other attribute It throws an error "TypeError: Cannot read property 'type_name' of undefined"

What am I doing wrong. Please help me

4
  • 1
    What is the initial value of this.state.devicetype? My guess is that your component is rendering before this.state.devicetype.data is set in response to the axios call, so the initial render is trying to access an object that does not exist (yet). Commented Feb 5, 2019 at 19:40
  • @christian my initial value of this.state.devicetype is {} empty object. Commented Feb 5, 2019 at 19:43
  • If my component is rendering before "this.state.devicetype.data" is set to the axios call. Then how do I fix it. Commented Feb 5, 2019 at 19:48
  • It depends on how you want your UI to handle this case. Usually this behavior is desirable as it gives you the opportunity to show a "Loading..." message while your data is being loaded, otherwise your component would not render until your data is loaded. You can add an if-statement to your render() function to handle the case where data is not yet loaded. In pseudocode: if (dataIsNotLoaded) displayLoadingMessage else displayData Commented Feb 5, 2019 at 20:04

1 Answer 1

2

You need to do conditional check before accessing nested objects like

   if(devicetype.data){
       console.log(devicetype.data.device_elements);
       console.log(devicetype.data.type_name);
   }
Sign up to request clarification or add additional context in comments.

2 Comments

This method worked. Can you explain why it is necessary to do a conditional check before accessing nested object. Thanks
because devicetype.data is undefined or null on initial render but you are directly accessing devicetype.data.type_name which won’t work because in initial render devicetype.data is undefined

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.