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