Как мне оформить компонент react на основе нескольких условий?

#reactjs #react-native #conditional-operator #conditional-rendering

#reactjs #react-native #условный оператор #условный рендеринг

Вопрос:

У меня есть список продуктов с указанием сроков годности. Я хочу применять стили в зависимости от того, истекает ли срок действия моего элемента сегодня, не истекает сегодня или уже истек.(Может быть еще много условий, с которыми я хочу работать).
Мне успешно удалось сделать это с помощью вложенного троичного оператора или с помощью массива стилей с троичным оператором, как показано ниже.

  <ListItem  
     containerStyle={
          [exp_check === -1 ? { backgroundColor: '#ff9ea5' } : null,
                exp_check === 0 ? { backgroundColor: '#fff185' } : null]
                    }
     badge={
          exp_check !== 1 ?
               exp_check === -1 ? { status: 'error', value: `!` } : { status: 'warning'} : null
           }
/>
  

Есть ли способ добиться чего-то вроде инструкции switch для стиля или для любого другого реквизита, если на то пошло. Я хочу иметь возможность легко устанавливать свои реквизиты условно без необходимости писать вложенную логику или массивы. Что-то вроде :

 stlye / badge / any prop accepted by the component = {
switch(something):
CASE1: ..
CASE2:.. 
etc etc 
CASE N:
}
  

Я не уверен, смогу ли я написать оператор IF / ELSE внутри prop, потому что я не смог заставить его скомпилироваться, если попытаюсь это сделать.

Комментарии:

1. Почему бы не вычислить его перед рендерингом? Сложная логика принадлежит местам, подходящим для сложной логики.

2. Как мне это сделать? Я думаю, что могу заставить мою функцию проверки истечения срока действия возвращать строку и обращаться к моему объекту таблицы стилей, используя эту строку, но это все еще кажется хакерским.

3. Поместите это в код перед началом рендеринга? Неясно, в чем заключается основная проблема.

4. Да, я понял, я просто слишком долго смотрел на экран, я думаю.

Ответ №1:

Рассмотрим подход, при котором у вас есть функция категоризации, которая помещает данный элемент в определенную группу, а затем сопоставляет реквизиты, стили или имена классов с группами.

 const ONE_HOUR = 1000 * 60 * 60;
const ONE_DAY = ONE_HOUR * 24;

// an array of status names/labels, each with a predicate function
// to test whether a given item matches. first match wins.
const bins = [
  {
    status: 'expired',
    predicate: time => time < Date.now(),
  },
  {
    status: 'urgent',
    predicate: time => Date.now() - time < ONE_HOUR
  },
  {
    status: 'soon',
    predicate: time => Date.now() - time < ONE_DAY,
  },
  {
    status: 'normal'
    predicate: () => true
  }
}

// find the first bin whose predicate function returns true for the item and use that bin's 'status'
const expirationStatus = bins.find(bin => bin.predicate(item.expirationTime)).status;

// now expirationStatus is one of 'expired', 'urgent', 'soon', or 'normal'
// which you can then use to assign styles or classNames or whatever:

// these could live in the bins too, as a 'style' or 'className' property or whatever.
const styles = {
  expired: {
    background: 'grey',
  },
  urgent: {
    background: 'red'
  },
  soon: {
    background: 'yellow'
  },
  normal: {
    background: 'green'
  }
}

return (
  <Component
    style={styles[expirationStatus]} {/* this */}
    status={expirationStatus} {/* and/or this */}
    className={expirationStatus} {/* and/or this */}
  />
)
  

Комментарии:

1. Спасибо, я сделал что-то подобное.