Отображение данных Javascript / React

Sep 26 2020

Мое решение реализовать статус (строку) из объединения двух других. Мне нужно объявить функцию, которая принимает два параметра (две строки) и должна возвращать еще один на основе комбинации этих двух строк. Например:

carStatus(status, secondaryStatus) => string

где secondaryStatus может иметь несколько параметров. Я использую оператор if / else if, который возвращает третий статус, который мне нужен. Например, когда статус - «ОТКРЫТО», а вторичный статус - «payment1», «payment2» или «payment3», функция должна возвращать новую строку (статус), например «CONFIRMED». Итак, мое решение на данный момент будет примерно таким:

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>

В div должно быть указано «ПОДТВЕРЖДЕНО».

В моей реализации я должен написать еще 5 операторов else if ... так что, возможно, есть более чистый способ реализовать это.

Любая помощь будет оценена по достоинству.

Ответы

3 CertainPerformance Sep 26 2020 at 22:01

Ошибка условия В вашей текущей реализации есть ошибка. У ваших строк, подобных этим, есть проблема:

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

В JavaScript есть только унарные операторы, бинарные операторы и один тернарный оператор. Все использованные выше операторы являются бинарными операторами; два выражения будут преобразованы в одно выражение, пока не останется одно. Поскольку ===имеет более высокий приоритет оператора, чем ||, ваш код эквивалентен:

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

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

payment2И payment3не сравниваются с secondaryStatus, и если secondaryStatusэто не payment1, все выражение будет вычисляться 'payment2', значение truthy (потому что ||будет оценивать на второе значение , если первый falsey):

// || operates left-to-right:

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

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

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

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

Чтобы исправить логику, используйте вместо этого массив и проверьте статус каждого элемента в массиве.

Опечатка? У вас есть (secondaryStatus === 'payment2' || 'payment5' || 'payment5'), причем payment5дважды. Вы имели в виду что-то еще, например payment9?

Имена carStatus не содержат статуса автомобиля, как это могло бы звучать; это функция, которая при вызове возвращает статус автомобиля. Он также принимает параметр с похожим названием status. Назовите их как-нибудь иначе, если это вообще возможно: возможно, getCarStatusи что-то более конкретное, что statusпредставляет параметр. Может позвонить secondaryStatus: paymentType.

DRY Вы также хотите сделать код более СУХИМ, что хорошо согласуется с идеей использования массивов. Вы можете использовать объект, ключи которого - это требуемый статус, а значения - возможные secondaryStatusзначения, а также возвращаемое значение, если secondaryStatusон найден.

Кроме того, поскольку все строки оплаты заканчиваются числом, и это число - единственное, что изменяется, используйте этот номер для настройки объекта конфигурации вместо полных paymentстрок:

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

Живой фрагмент:

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

Тип компонента Похоже, вы используете компонент класса. React рекомендует попробовать использовать функциональные компоненты в новом коде; они говорят, что с ними немного легче работать и понимать, чем компоненты на основе классов в большинстве случаев, и я согласен. Вместо этого попробуйте использовать функциональные компоненты, если вы еще этого не сделали, они могут вам понравиться.