Mapper danych Javascript / React

Sep 26 2020

Moje rozwiązanie do implementacji statusu (string) z połączenia dwóch innych. Muszę zadeklarować funkcję, która przyjmuje dwa parametry (dwa ciągi) i musi zwrócić inny w oparciu o kombinację tych dwóch ciągów. Na przykład:

carStatus(status, secondaryStatus) => string

gdzie status secondaryStatus może mieć wiele opcji. Używam instrukcji if / else if, która zwraca trzeci status, którego potrzebuję. Na przykład, gdy status to „OPEN”, a status wtórny to „payment1”, „payment2” lub „payment3”, funkcja musi zwrócić nowy ciąg znaków (status), np. „CONFIRMED”. Więc moje rozwiązanie w tej chwili wyglądałoby mniej więcej tak:

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>

W div musi być renderowane jako „POTWIERDZONE”.

W mojej implementacji będę musiał napisać, myślę, inne 5 innych instrukcji if .. więc może istnieje bardziej przejrzysty sposób na wdrożenie tego.

Każda pomoc zostanie doceniona.

Odpowiedzi

3 CertainPerformance Sep 26 2020 at 22:01

Błąd stanu Twoja bieżąca implementacja zawiera błąd. Twoje linie, takie jak te, mają problem:

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

JavaScript ma tylko operatory jednoargumentowe, operatory binarne i jeden operator trójskładnikowy. Wszystkie operatory użyte powyżej są operatorami binarnymi; dwa wyrażenia zostaną przekształcone w jedno wyrażenie, aż pozostanie jedno. Ponieważ ===ma wyższy priorytet operatora niż ||, Twój kod jest równoważny z:

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

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

Elementy payment2i payment3nie są porównywane z secondaryStatus, a jeśli secondaryStatusnie payment1, to całe wyrażenie zwróci 'payment2'prawdziwą wartość (ponieważ ||zostanie zwrócona druga wartość, jeśli pierwsza jest błędna):

// || operates left-to-right:

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

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

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

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

Aby naprawić logikę, użyj zamiast niej tablicy i sprawdź stan każdego elementu tablicy.

Literówka? Masz (secondaryStatus === 'payment2' || 'payment5' || 'payment5'), z payment5powtórzonym dwukrotnie. Miałeś na myśli coś innego, jak payment9?

Nazwy carStatus nie zawierają statusu samochodu, jak mogłoby się wydawać, że zawiera; jest to funkcja, która po wywołaniu zwraca stan samochodu. Pobiera również myląco podobnie nazwany statusparametr. Nazwij je inaczej, jeśli to w ogóle możliwe: być może getCarStatusi cokolwiek bardziej szczegółowego statusreprezentuje parametr. Może zadzwoń secondaryStatus: paymentType.

DRY Chcesz również, aby kod był bardziej SUCHY, co dobrze pasuje do pomysłu używania zamiast tego tablic. Możesz użyć obiektu, którego klucze są wymaganym stanem i którego wartości są możliwymi secondaryStatuswartościami, a także wartością zwracaną, jeśli secondaryStatuszostanie znaleziony.

Ponadto, ponieważ wszystkie ciągi płatności kończą się liczbą, a ta liczba jest jedyną rzeczą, która się zmienia, użyj tej liczby do skonfigurowania obiektu konfiguracyjnego zamiast pełnych paymentciągów:

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

Fragment na żywo:

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')
);

Typ komponentu Wygląda na to, że używasz komponentu klasy. React zaleca wypróbowanie użycia komponentów funkcjonalnych w nowym kodzie; mówią, że są nieco łatwiejsze w obsłudze i zrozumieniu niż komponenty oparte na klasach w większości przypadków i zgadzam się z tym. Spróbuj zamiast tego użyć komponentów funkcjonalnych, jeśli jeszcze tego nie zrobiłeś, możesz je polubić.