Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for deeply nested props

I often find myself having to build long chains before mapping over an array to check if it's defined:

this.props.photos &&
this.props.photos.activePhotos &&
this.props.photos.activePhotos.map(...

If I leave out the this.props.photos && and this.props.photos.activePhotos.length && my entire application will crash if photos or activePhotos is undefined.

Is there a way to check for these props without having to check every parent object/array of my end item?

like image 999
cubefox Avatar asked Feb 19 '19 10:02

cubefox


People also ask

How can you tell if an object has a nested object?

To check if an object has a nested property, use the optional chaining operator - ?. . The ?. operator allows you to read the value of a nested property without throwing an error if the property does not exist on the object, e.g. obj?.

How do you check if a value exists in a nested object Javascript?

Show activity on this post. var a; a = { b: { c: 'd' } }; function isset (fn) { var value; try { value = fn(); } catch (e) { value = undefined; } finally { return value !== undefined; } }; // ES5 console. log( isset(function () { return a.


3 Answers

January 2020 Update

According to the TC39 proposal, optional chaining will be available shortly within the JavaScript standard (currently in stage 4).

The syntax will be the following :

const active = this.props?.photos?.activePhotos

Or the following in your case :

(this.props?.photos?.activePhotos || []).map(...

While this is being implemented, you may want to take a look at Typescript or js compilers to try out the latest ES features


Old answer

An alternative could be to use a default value for your props when deconstructing them :

  const { photos = {} } = this.props
  const { activePhotos = [] } = photos
  activePhotos.map(/*   */)

In this case, if photos is not defined, it will be replaced with an empty object. Trying to get the activePhotos out of it will give you an empty array, allowing you to map on it in any case.

like image 154
Treycos Avatar answered Oct 06 '22 01:10

Treycos


I guess you refer to optional chaining, which is stage 1 of TC39

https://github.com/tc39/proposal-optional-chaining

EDIT: The proposal is now in stage 4 (as of January 2020) and will be added into the JavaScript standard

like image 42
samb102 Avatar answered Oct 06 '22 03:10

samb102


I'm seeing two possible approaches, according to the level of nesting.

#1. If you have many nested props levels:

You can use lodash.get.

Here's how to render activePhotos, only if they exists:

// Please note how do we pass default `[]` as third parameter
// in order to not break the `.map` function
_.get(this.props, 'photos.activePhotos', []).map(...)

If you only want to check for deeply nested pros, then you can use lodash.has method:

// Will return `true` / `false`
_.has(this.props, 'photos.activePhotos')

#2. If the level of nesting is no more of 2-3 levels:

Just use the native ES6 destructuring assignment + default value feature.

const { photos = {} } = this.props
const { activePhotos = [] } = photos

// Now you can safely map over the `activePhotos`
activePhotos.map(...)
like image 27
Jordan Enev Avatar answered Oct 06 '22 02:10

Jordan Enev