I have a simple React Component, and am trying to display a nested JSON object in render. 
// React Component
class NodeDetail extends React.Component {
  constructor(props) {
    super(props);
    const node = {};
    this.state = {
      node
    }
  }
  componentDidMount() {
    Node.getNode(this.props.node_id).then((result) => {
      console.log(result.data);
      this.setState(() => ({node: result.data}));
    }).catch(function(error) {
      // TODO: handle error
    });
  }
  render() {
    return (
      <div>
        {this.state.node.node_status.name}
      </div>
    );
  }
};
export default NodeDetail;
This is the JSON(stored in result.data) getting returned from a rails API(some fields removed for brevity):
{  
   "id":1234,
   "name":"some-node",
   "created_at":"2018-05-18T15:23:24.012Z",
   "hostname":"some-host",
   "ip":"10.XXX.XXX.XXX",
   "mac":"24:6e:96:XX:11:XX",
   "node_status":{  
      "id":2,
      "name":"Parked"
   }
}
When I access the root level attributes in React with this.state.node.mac , it returns 24:6e:96:XX:11:XX. 
When I try to access the name attribute in node_status using this.state.node.node_status.name, I get the the following error:
Uncaught TypeError: Cannot read property 'name' of undefined
I have also tried this.state.node['node_status'].name, and same error. 
Why can't I access this object in the JSON, when clearly it is there?
I bet it's because your call to the Rails API is asynchronous -- so your NodeDetail component tries to render before the API returns data / state is set with the result.data...try putting in a condition for non-existent node_status as some of the other answers have suggested.
So the current (wrong) data flow will be:
constructor. state is set to {node: {}}
componentDidMount. Calls API.render. Throws exception because this.state.node.node_status is undefined. Component breaks and won't render again...state is set to result.data. result.data gets logged to your console.What you can do is something like:
render() {
    if (!this.state.node.node_status) {
      return null;
    }
    return (
      <div>
        {this.state.node.node_status.name}
      </div>
    );
  }
Or any of the other suggestions to account for the undefined value of this.state.node.node_status.
In general, you need to make sure that your render method will work, even with the default state values set in your constructor.
Error is coming correct Your are fetching data after component loaded  In short you are calling your API in componentDidMount
You can get rid off from this error in this way
 <div>
        {this.state.node.node_status?this.state.node.node_status.name:""}
 </div>
and I would suggest you to  call fetch data API in componentWillMount or constructor which is the initial stage of component.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With