Mappatore dati Javascript / React

Sep 26 2020

La mia soluzione per implementare uno stato (stringa) combinando altri due. Devo dichiarare una funzione che accetta due parametri (due stringhe) e deve restituirne un altro in base alla combinazione di queste due stringhe. Ad esempio:

carStatus(status, secondaryStatus) => string

dove secondarioStatus può avere più opzioni. Sto usando un'istruzione if / else if che restituisce un terzo stato di cui ho bisogno. Ad esempio, quando lo stato è "APERTO" e secondarioStato è "pagamento1" o "pagamento2" o "pagamento3", la funzione deve restituire una nuova stringa (stato) come "CONFERMATO". Quindi, la mia soluzione in questo momento sarebbe qualcosa del genere:

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>

In div deve essere reso "CONFERMATO".

Nella mia implementazione, dovrò scrivere penso che altre 5 istruzioni if ​​.. quindi forse c'è un modo più pulito per implementarlo.

Qualsiasi aiuto sarà apprezzato.

Risposte

3 CertainPerformance Sep 26 2020 at 22:01

Condizione bug La tua attuale implementazione ha un bug. Le tue linee come queste hanno il problema:

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

JavaScript ha solo operatori unari, operatori binari e un singolo operatore ternario. Tutti gli operatori usati sopra sono operatori binari; due espressioni verranno valutate in una singola espressione finché non ne rimane una sola. Poiché ===ha una precedenza operatore maggiore di ||, il tuo codice è equivalente a:

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

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

I payment2e payment3non vengono confrontati con secondaryStatus, e in caso secondaryStatuscontrario payment1, l'intera espressione 'payment2'restituirà un valore vero (perché ||valuterà il secondo valore se il primo è falso):

// || operates left-to-right:

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

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

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

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

Per correggere la logica, utilizzare invece un array e controllare lo stato rispetto a ciascun elemento dell'array.

Errore di battitura? Lei ha (secondaryStatus === 'payment2' || 'payment5' || 'payment5'), con payment5ripetute due volte. Intendevi qualcos'altro, come payment9?

I nomi carStatus non contengono lo stato dell'auto, poiché sembrerebbe contenere; è una funzione che, se chiamata, restituisce lo stato dell'auto. Richiede anche un statusparametro dal nome simile a confusione . Chiamali qualcos'altro, se possibile: forse getCarStatuse qualunque cosa più specifica statusrappresentata dal parametro. Forse chiamare secondaryStatus: paymentType.

DRY Vuoi anche rendere il codice più DRY, che si adatta bene all'idea di usare invece gli array. È possibile utilizzare un oggetto le cui chiavi sono lo stato richiesto e i cui valori sono i secondaryStatusvalori possibili , nonché il valore restituito se secondaryStatusviene trovato.

Inoltre, poiché tutte le stringhe di pagamento terminano con un numero e quel numero è l'unica cosa che cambia, usa quel numero per impostare l'oggetto di configurazione invece delle paymentstringhe complete :

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;
        }
    }
}

Snippet dal 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 di componente Sembra che tu stia utilizzando un componente di classe. React consiglia di provare a utilizzare componenti funzionali nel nuovo codice; dicono che sono un po 'più facili da lavorare e da capire rispetto ai componenti basati sulla classe nella maggior parte delle circostanze, e sono d'accordo. Prova invece a utilizzare componenti funzionali, se non l'hai già fatto, potrebbero piacerti.