简体   繁体   English

如何检查深度嵌套的 props

[英]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.如果我省略了this.props.photos &&this.props.photos.activePhotos.length &&如果photosactivePhotos未定义,我的整个应用程序将崩溃。

Is there a way to check for these props without having to check every parent object/array of my end item?有没有办法检查这些道具而不必检查我的最终项目的每个父对象/数组?

January 2020 Update 2020 年 1 月更新

According to the TC39 proposal , optional chaining will be available shortly within the JavaScript standard (currently in stage 4 ).根据TC39 提案可选链将很快在 JavaScript 标准中可用(目前处于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在实现这一点时,您可能需要查看 Typescript 或 js 编译器以尝试最新的 ES 功能


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.在这种情况下,如果没有定义photos ,它将被替换为一个空对象。 Trying to get the activePhotos out of it will give you an empty array, allowing you to map on it in any case.试图activePhotos取出activePhotos会给你一个空数组,让你在任何情况下都可以映射它。

I guess you refer to optional chaining, which is stage 1 of TC39我猜你指的是可选链接,这是 TC39 的第 1 阶段

https://github.com/tc39/proposal-optional-chaining 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编辑:该提案现在处于第 4 阶段(截至 2020 年 1 月),并将被添加到 JavaScript 标准中

I'm seeing two possible approaches, according to the level of nesting.根据嵌套级别,我看到了两种可能的方法。

#1. #1. If you have many nested props levels:如果您有许多嵌套的道具级别:

You can use lodash.get .您可以使用lodash.get

Here's how to render activePhotos , only if they exists:以下是渲染activePhotos ,仅当它们存在时:

// 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:如果你只想检查深度嵌套的优点,那么你可以使用lodash.has方法:

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

#2. #2. If the level of nesting is no more of 2-3 levels:如果嵌套级别不超过 2-3 级:

Just use the native ES6 destructuring assignment + default value feature.只需使用原生 ES6 解构赋值 + 默认值功能。

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

// Now you can safely map over the `activePhotos`
activePhotos.map(...)

Is there a way to check for these props without having to check every parent object/array of my end item?有没有办法检查这些道具而不必检查我的最终项目的每个父对象/数组?

In general, no.一般来说,没有。

It is not clear why the .length of the potential is checked at the code at the question.目前尚不清楚为什么在问题的代码中检查潜力的.length

If the goal is to reduce the code length you can us JSON.stringify() and RegExp如果目标是减少代码长度,您可以使用JSON.stringify()RegExp

if (/"activePhotos":\[.*\]/.test(JSON.stringify(this.props))) // do stuff

or if the preferred approach is using AND operator或者如果首选方法是使用AND运算符

/"activePhotos":\[.*\]/.test(JSON.stringify(this.props)) && // do stuff

undefsafe is a good enough library to use. undefsafe是一个足够好的库来使用。 There are lot of other libraries available as well.还有很多其他库可用。

Simple example of how to use it如何使用它的简单示例

var object = {
  a: {
    b: {
      c: 1,
      d: [1,2,3],
      e: 'remy'
    }
  }
};

console.log(undefsafe(object, 'a.b.e')); // "remy"
console.log(undefsafe(object, 'a.b.not.found')); // undefined

Here is a functional approach to optional chaining with default value return.这是一种带有默认值返回的可选链接功能方法 The method uses a Maybe monad and a Proxy .该方法使用了一个Maybe monad 和一个Proxy

A wrap() function is used to wrap objects on which you can access any property safely. wrap()函数用于包装可以安全访问任何属性的对象。 Internally, wrap creates a Proxy around your object and manages missing values using a Maybe wrapper.在内部, wrap在您的对象周围创建一个代理并使用 Maybe 包装器管理缺失值。 At the end of the chain, you unwrap the value by chaining getOrElse(default) with a default value which is returned when the propertie access fails:在链的末尾,您通过将getOrElse(default)与默认值链接getOrElse(default)解包该值,该默认值在属性访问失败时返回:

 class Maybe { constructor(value) { this.__value = value; } static of(value){ if (value instanceof Maybe) return value; return new Maybe(value); } getOrElse(elseVal) { return this.isNothing() ? elseVal : this.__value; } isNothing() { return this.__value === null || this.__value === undefined; } map(fn) { return this.isNothing() ? Maybe.of(null) : Maybe.of(fn(this.__value)); } } function wrap(obj) { function fix(object, property) { const value = object[property]; return typeof value === 'function' ? value.bind(object) : value; } return new Proxy(Maybe.of(obj), { get: function(target, property) { if (property in target) { return fix(target, property); } else { return wrap(target.map(val => fix(val, property))); } } }); } const obj = { a: 1, b: { c: [4, 1, 2] }, c: () => 'yes' }; console.log(wrap(obj).a.getOrElse(null)) // returns 1 console.log(wrap(obj).abcdefgetOrElse(null)) // returns null console.log(wrap(obj).bcgetOrElse([])) // returns [4, 1, 2] console.log(wrap(obj).bc[0].getOrElse(null)) // returns 4 console.log(wrap(obj).bc[100].getOrElse(-1)) // out-of-bounds index: returns -1 console.log(wrap(obj).c.getOrElse(() => 'no')()) // returns 'yes' console.log(wrap(obj).d.getOrElse(() => 'no')()) // returns 'no'

See this blog post and this link for more information on Maybe monads and the use of proxies.有关 Maybe monads 和代理使用的更多信息,请参阅此博客文章此链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM