3

I have a simple, quick question. There's a lot of situation where we have to check if props are undefined.

What about nested props, for example we have:

this.props.data.income.data1.value.chartData

and we want to check if chartData exist

it has to be a better, more clear way than

if(
this.props.data && 
this.props.data.income && 
this.props.data.income.data1 &&     
this.props.data.income.data1.value && 
this.props.data.income.data1.value.chartData!==null
)

I cant just check this.props.data.income.data1.value.chartData!==null

Please tell me how do you solve it in your projects?

klijakub
  • 845
  • 11
  • 31
  • 5
    Possible duplicate of [Test for existence of nested JavaScript object key](https://stackoverflow.com/questions/2631001/test-for-existence-of-nested-javascript-object-key) – imjared May 21 '18 at 07:54

5 Answers5

4

I'm a fan of using lodash's _.get().

You can search as deep as you want in objects and if there's nothing there, it won't throw an error. To use your example:

_.get(this.props.data, 'income.data1.value.chartData')

would either return the chartData or undefined if there was no income, data1, value, or chartData

imjared
  • 19,492
  • 4
  • 49
  • 72
  • 1
    Using an immutable library (such as immutable.js) allows you to do something similar as well. – Bill May 21 '18 at 07:56
  • Wow! interesting approach! I'm curious if this doesn't slow down app a little? – klijakub May 21 '18 at 07:59
  • This might be good, but if we are to add such packages for various implementations, wouldn't it add to package size hereby decreasing performance? – Aseem Upadhyay May 21 '18 at 08:20
  • 1
    If you're optimizing performance such that a 24kb library (or a < 1kb method if you're using Webpack) is a problem, then we're working in very different worlds and you might want to roll your own solution – imjared May 21 '18 at 11:35
2

Take a look at optional chaining - you'll currently need to use a babel plugin in order to use it, but the proposal is to make this approach available in native JS. It allows you to reference object properties like so:

this.props.data?.income?.data1?.value?.chartData?

were any of the properties ending with ? may not exist.

delinear
  • 2,745
  • 1
  • 10
  • 21
1

There can be multiple approaches to this problem.

  1. You can make your components dependent on the prop values .i.e. if an object is rendering, it is implied that the extensive checks of data objects are not needed since they are already present.
  2. You can define new props at every component that are just breakdown of all the prop values. I wouldn't recommend this because this would mean you'll need to handle validation of multiple props objects.
  3. And lastly, probably breakdown your data structure into something simpler.
Aseem Upadhyay
  • 4,279
  • 3
  • 16
  • 36
1

You can use underscore js. you can use this as reference http://underscorejs.org/#has

_.has(object, key)
Does the object contain the given key? Identical to object.hasOwnProperty(key), but uses a safe reference to the hasOwnProperty

_.has({a: 1, b: 2, c: 3}, "b");
=> true

similarly you can use like this

_.has(this.props, "data")
it will return either true or false. 
dhivya s
  • 294
  • 1
  • 7
0

This is what I do in such cases:

((((this.props.data || {}).income || {}).data1 || {}).value || {}).chartData !== null

This basically breaks each object property down one-by-one. By doing [property] || {} you are checking if property exists, otherwise create an empty object so that the next check won't throw you an error.

If you are wondering why this works, consider this example:

const a = {b: "foo bar"};

a.b // "foo bar"
a.c // undefined
a.c.d // ERROR!

Here, c isn't a valid key for the object a, so you get undefined which is still okay. However, you can't ask for the key d for the non-existing object c. That's when you get an error.

To tackle this, you can create a new object {} and work on that. It's an empty object, so it will always return undefined, but by doing this one level at a time, you will never get an error.

Not a visually pretty solution, but it does save you a few lines.

Chris
  • 57,622
  • 19
  • 111
  • 137