javascript reactjs

javascript - ¿Cómo manejar las funciones de llamada en datos que pueden estar indefinidos?



reactjs (2)

Compruebe la matriz antes de usar el mapa:

arr && arr.map()

O,

arr && arr.length && arr.map() // if you want to map only if not empty array

O,

Incluso podemos usarlo así (como lo comenta devserkan ):

(arr || []).map()

Según su comentario:

Me gustaría que hubiera un operador de navegación seguro como con C # (arr? .Map ())

Si obviamente. Esto se denomina encadenamiento opcional en JavaScript que aún está en propuesta. Si es aceptado, entonces puedes usar así:

arr?.map()

Puedes verlo en el escenario 1 para el que puedes usar babel preset stage1

Pero obviamente, excepto la longitud de la matriz de verificación, su requisito no se cumplirá:

Esto da como resultado un error porque, por supuesto, el primer índice de la matriz no está definido.

Por lo tanto, te sugiero que uses:

arr && arr.length && arr.map()

Principalmente trabajo con React y, a menudo, encuentro que cuando escribo una función que se basa en el estado de un componente, tengo que realizar una verificación para ver si el estado está definido antes de realizar cualquier acción.

Por ejemplo: tengo una función que utiliza .map() para recorrer una matriz de objetos recuperados de una base de datos y genera jsx para cada objeto de la matriz. Esta función se llama en la función render() de mi componente. La primera vez render() se llama a render() , la matriz inicial está vacía. Esto da como resultado un error porque, por supuesto, el primer índice de la matriz no está definido.

He estado evadiendo esto haciendo una verificación condicional para ver si el valor de la matriz no está definido o no. Este proceso de escribir una declaración if cada vez se siente un poco torpe y me preguntaba si hay una mejor manera de realizar esta comprobación o una forma de evitarla por completo.


Lo que realmente necesita aquí se llama encadenamiento opcional :

obj?.a?.b?.c // no error if a, b, or c don''t exist or are undefined/null

El ?. es el operador existencial y le permite acceder a las propiedades de forma segura y no tirar si falta la propiedad. Sin embargo, el encadenamiento opcional aún no forma parte de JavaScript, pero se ha propuesto, consulte el estado 1 de TC39 .

Pero, utilizando proxies y una clase Maybe , puede implementar el encadenamiento opcional y devolver un valor predeterminado cuando la cadena falla.

Se utiliza una función wrap() para envolver los objetos en los que desea aplicar el encadenamiento opcional. Internamente, la wrap crea un Proxy alrededor de su objeto y administra los valores faltantes usando una envoltura Maybe .

Al final de la cadena, desenvuelve el valor encadenando getOrElse(default) con un valor predeterminado que se devuelve cuando la cadena no es válida:

const obj = { a: 1, b: { c: [4, 1, 2] }, c: () => ''yes'' }; console.log(wrap(obj).a.getOrElse(null)) // returns 1 console.log(wrap(obj).a.b.c.d.e.f.getOrElse(null)) // returns null console.log(wrap(obj).b.c.getOrElse([])) // returns [4, 1, 2] console.log(wrap(obj).b.c[0].getOrElse(null)) // returns 4 console.log(wrap(obj).b.c[100].getOrElse(-1)) // returns -1 console.log(wrap(obj).c.getOrElse(() => ''no'')()) // returns ''yes'' console.log(wrap(obj).d.getOrElse(() => ''no'')()) // returns ''no'' wrap(obj).noArray.getOrElse([1]).forEach(v => console.log(v)) // Shows 1 wrap(obj).b.c.getOrElse([]).forEach(v => console.log(v)) // Shows 4, 1, 2

El ejemplo completo:

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)) console.log(wrap(obj).a.b.c.d.e.f.getOrElse(null)) console.log(wrap(obj).b.c.getOrElse([])) console.log(wrap(obj).b.c[0].getOrElse(null)) console.log(wrap(obj).b.c[100].getOrElse(-1)) console.log(wrap(obj).c.getOrElse(() => ''no'')()) console.log(wrap(obj).d.getOrElse(() => ''no'')()) wrap(obj).noArray.getOrElse([1]).forEach(v => console.log(v)) // Shows 1 wrap(obj).b.c.getOrElse([]).forEach(v => console.log(v)) // Shows 4, 1, 2