Mapeador de datos de Javascript / React

Sep 26 2020

Mi solución para implementar un estado (cadena) al combinar otros dos. Necesito declarar una función que toma dos parámetros (dos cadenas) y necesita devolver otro basado en la combinación de esas dos cadenas. Por ejemplo:

carStatus(status, secondaryStatus) => string

donde secundariaStatus puede tener múltiples opciones. Estoy usando una declaración if / else if que devuelve un tercer estado que necesito. Por ejemplo, cuando el estado es 'ABIERTO' y el estado secundario es 'pago1' o 'pago2' o 'pago3', la función debe devolver una nueva cadena (estado) como 'CONFIRMADO'. Entonces, mi solución en este momento sería algo como esto:

carStatus = (status, secondaryStatus) => {
  if(status === 'OPEN' && (secondaryStatus === 'payment1' || 'payment2' || 'payment3')){
    return 'CONFIRMED';
  } else if(status === 'CANCELLED' && (secondaryStatus === 'payment4' || 'payment5' || 'payment6')){
    return 'REMOVED';
  } else if(status === 'REVIEW' && (secondaryStatus === 'payment2' || 'payment5' || 'payment5')){
    return 'CHECKED';
  }
}

<div>carStatus('OPEN', 'payment1')</div>

En div se debe renderizar 'CONFIRMADO'.

En mi implementación, tendré que escribir creo que otras 5 declaraciones else if ... así que tal vez haya una forma más limpia de implementar esto.

Se agradecerá cualquier ayuda.

Respuestas

3 CertainPerformance Sep 26 2020 at 22:01

Problema de condición Su implementación actual tiene un error. Tus líneas como estas tienen el problema:

(secondaryStatus === 'payment1' || 'payment2' || 'payment3')

JavaScript solo tiene operadores unarios, operadores binarios y un solo operador ternario. Todos los operadores utilizados anteriormente son operadores binarios; dos expresiones se evaluarán en una sola expresión hasta que quede una sola. Dado que ===tiene una precedencia de operadores mayor que ||, su código es equivalente a:

(secondaryStatus === 'payment1' || 'payment2' || 'payment3')

(trueOrFalse || 'payment2' || 'payment3')

Los payment2y payment3no se comparan con secondaryStatus, y si secondaryStatusno lo es payment1, toda la expresión se evaluará con 'payment2'un valor de verdad (porque ||se evaluará con el segundo valor si el primero es falso):

// || operates left-to-right:

(trueOrFalse || 'payment2' || 'payment3')

((false || 'payment2') || 'payment3')

(('payment2') || 'payment3')

// payment2 is truthy, so the `||` evaluates to it:
('payment2')

Para corregir la lógica, use una matriz en su lugar y verifique el estado con cada elemento de la matriz.

¿Error de tipografía? Tienes (secondaryStatus === 'payment2' || 'payment5' || 'payment5'), con payment5repetido dos veces. ¿Querías decir algo más, como payment9?

Los nombres carStatus no contienen el estado del automóvil, como parecería contener; es una función que, cuando se llama, devuelve el estado del coche. También toma un statusparámetro de nombre similar y confuso . Llámelos de otra manera, si es posible: quizás getCarStatusy cualquier cosa más específica que statusrepresente el parámetro. Tal vez llame a secondaryStatus: paymentType.

DRY También desea que el código sea más DRY, lo que encaja bien con la idea de usar matrices en su lugar. Puede usar un objeto cuyas claves sean el estado requerido y cuyos valores sean los secondaryStatusvalores posibles , así como el valor de retorno si secondaryStatusse encuentra.

Además, dado que todas las cadenas de pago terminan en un número, y ese número es lo único que cambia, use ese número para configurar el objeto de configuración en lugar de las paymentcadenas completas :

const statusOptions = {
    OPEN:      { paymentNumbers: [1, 2, 3], status: 'CONFIRMED' },
    CANCELLED: { paymentNumbers: [4, 5, 6], status: 'REMOVED' },
    REVIEW:    { paymentNumbers: [2, 5], status: 'CHECKED' },
};
// ...
getCarStatus = (status, paymentType) => {
    const possibleOption = statusOptions[status];
    if (possibleOption) {
        const paymentNumber = Number(paymentType.match(/\d+$/)[0]);
        if (possibleOption.paymentNumbers.includes(paymentNumber)) {
            return possibleOption.status;
        }
    }
}

Fragmento en vivo:

const statusOptions = {
    OPEN:      { paymentNumbers: [1, 2, 3], status: 'CONFIRMED' },
    CANCELLED: { paymentNumbers: [4, 5, 6], status: 'REMOVED' },
    REVIEW:    { paymentNumbers: [2, 5], status: 'CHECKED' },
};
// ...
getCarStatus = (status, paymentType) => {
    const possibleOption = statusOptions[status];
    if (possibleOption) {
        const paymentNumber = Number(paymentType.match(/\d+$/)[0]);
        if (possibleOption.paymentNumbers.includes(paymentNumber)) {
            return possibleOption.status;
        }
    }
};

console.log(
  getCarStatus('OPEN', 'payment3'),
  getCarStatus('REVIEW', 'payment2')
);

Tipo de componente Parece que está utilizando un componente de clase. React recomienda que pruebe utilizando componentes funcionales en código nuevo; dicen que es un poco más fácil trabajar con ellos y entenderlos que los componentes basados ​​en clases en la mayoría de las circunstancias, y estoy de acuerdo. En su lugar, intente usar componentes funcionales, si aún no lo ha hecho, es posible que le gusten.