Mapper danych Javascript / React
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
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ć.