I am using React to build a simple app that gets data back from some API. I am not sure what is the best way to handle the fields when some of them doesnt e back. For example, Let's say the JSON data es back looking like the following
icDetail : {
name : iron man,
age: {
icAge: 35,
},
favouriteFood: {
fruit: {
apple
}
}
hobby: {
favourite: {
build machines
}
}
series: [iron man 1, iron man 2]
relationship: {
jane: iron man 1,
Mary: iron man 2
},
collection : {
image : www.image1
}
}
}
My React code that renders the data
renderComicDetail() {
var cd = this.propsicDetail;
if (!cd) {
return (
<div>No Data</div>
)
}
const imageUrl = cd.collection.image
return (
<div>
<div>age: {cd.ageicAge}</div>
<div>favourite fruit: {cd.favouriteFood.fruit}</div>
<div>favourite hobby: {cd.hobby.favourite}</div>
</div>
)
}
This code will break if either of the of cd.favouriteFood, cd.age, cd.hobby is undefined as I will be reading from undefined. (This will happen as not all fields will e back) What is the cleanest way to allow me to read the data and take care of the undefined case so I dont read .fruit from undefined.
A way I can think of is to have check cases for each part of the json data for every item. But it seems messy and will not be scalable as I might have data that looks like
I am using React to build a simple app that gets data back from some API. I am not sure what is the best way to handle the fields when some of them doesnt e back. For example, Let's say the JSON data es back looking like the following
icDetail : {
name : iron man,
age: {
icAge: 35,
},
favouriteFood: {
fruit: {
apple
}
}
hobby: {
favourite: {
build machines
}
}
series: [iron man 1, iron man 2]
relationship: {
jane: iron man 1,
Mary: iron man 2
},
collection : {
image : www.image1.
}
}
}
My React code that renders the data
renderComicDetail() {
var cd = this.props.icDetail;
if (!cd) {
return (
<div>No Data</div>
)
}
const imageUrl = cd.collection.image
return (
<div>
<div>age: {cd.age.icAge}</div>
<div>favourite fruit: {cd.favouriteFood.fruit}</div>
<div>favourite hobby: {cd.hobby.favourite}</div>
</div>
)
}
This code will break if either of the of cd.favouriteFood, cd.age, cd.hobby is undefined as I will be reading from undefined. (This will happen as not all fields will e back) What is the cleanest way to allow me to read the data and take care of the undefined case so I dont read .fruit from undefined.
A way I can think of is to have check cases for each part of the json data for every item. But it seems messy and will not be scalable as I might have data that looks like
Share Improve this question asked Apr 29, 2017 at 4:17 ErnieKevErnieKev 3,0415 gold badges23 silver badges35 bronze badges 1- You can do conditional rendering and then do a check to see if the specific part is undefined before accessing it. – Andrew Li Commented Apr 29, 2017 at 4:20
7 Answers
Reset to default 2You can specify a condition to render a ponent in JSX, your code would look something like this (assuming that if hobby or food are defined then it would have renderable properties):
var cd = this.props.icDetail;
if (!cd) {
return (
<div>No Data</div>
)
}
const imageUrl = cd.collection.image;
return (
<div>
<div>age: {cd.age.icAge}</div>
{cd.favouriteFood && <div>favourite fruit: {cd.favouriteFood.fruit}</div>}
{cd.hobby && <div>favourite hobby: {cd.hobby.favourite}</div>}
</div>
)
I also advice you to either create separate ponet for both hobby and food, so it can make your code more readable and reusable. But it definitely depends on your specific usage.
if you only don't want to display content which is undefined, you can do like this:
return (
<div>
{cd.age && cd.age.icAge ? <div>age:{cd.age.icAge}</div> : <div>No data</div>
}
{cd.favouriteFood && cd.favouriteFood.fruit ? <div>favourite fruit: {cd.favouriteFood.fruit}</div> : <div>No data</div>
}
{cd.hobby && cd.hobby.favourite ? <div>favourite hobby: {cd.hobby.favourite}</div> : <div>No data</div>
}
</div>
)
or if you don't want like this, create a separate function that checks valid fields
if (!isValid(cd)) {
return (
<div>No Data</div>
)
}
isValid(obj){
// check if all objects available are valid or not and return true or false as needed.
}
You can use any JSON schema validator for this purpose and there are lots of them. for e.g jsonschema
In your case you can create schema something like this ( for first two properties)
var schema = {
"id": "/ComicDetail",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "object",
"properties": {
"icAge": {
"type": "integer"
}
}
}
},
"required": ["name", "age"]
};
You can also embed two or more schema together and form a new schema.
One way to access deep object property using lodash. You can import lodash in your ponent.
_.get(cd, 'favouriteFood.fruit') || ''
https://lodash./docs/4.16.6#get
To make the code cleaner, You can also declare a function that takes your object(i.e. cd in your case) and path(i.e. favouriteFood.fruit in your case) and return the value from function.
I really like this method of un-nesting objects:
// Below will not error out, but give undefined when you use the non-existant variables
const { cd } = (this.props || {}).icDetail || {}
const { imageUrl } = ((cd || {}).collection || {}).image || {}
// Or
const { age, favouriteFood, hobby } = cd
const { icAge } = age // forgot if you need to add || {} here
const { fruit } = favouriteFood
const { favourite } = hobby
You always want to validate your variables and you never want your variables to break during validation.
So now, you can safely use these 'potentially' undefined variables and validate that they contain values before you use them.
favorite || 'defaultValue'
if (!favorite) return null
How about use ternary operator?
cd.age !== undefined ? cd.age.icAge : ' '
You can try your return statement such like that:
return (
<div>
{ cd.age.icAge && <div>age: {cd.age.icAge }</div>}
{ cd.favouriteFood.fruit && <div>favourite fruit: {cd.favouriteFood.fruit}</div> }
{cd.hobby.favourite && <div>favourite hobby: {cd.hobby.favourite}</div>
</div>
)
If your any prop is null or undefined, the right side of the condition is skipped.