Код-ревью Middle Компоненты и стили обновлено

Код-ревью: карточка товара

Вопрос

Компонент карточки товара. Найдите проблемы вёрстки, платформенных различий и производительности.

export const ProductCard = memo(({ product, onBuy }: Props) => {
  const { width } = Dimensions.get('window');
  return (
    <View style={{ width: width / 2, padding: 8, color: '#333', shadowOpacity: 0.2 }}>
      <Image source={{ uri: product.photoUrl }} />
      {product.discount && <Text>-{product.discount}%</Text>}
      <View>{product.title}</View>
      <TouchableOpacity onPress={() => onBuy(product.id)} style={{ height: 24 }}>
        <Text>Купить</Text>
      </TouchableOpacity>
    </View>
  );
});

Коротко

Классические ошибки перехода с веба: текст вне Text, ожидание наследования стилей, && с числом, картинка без размеров. Плюс платформенные тени и снимок размеров вместо хука.

Что должен найти ревьюер

  1. Ошибкастрока 2
    Dimensions.get даёт снимок и не обновится при повороте или split view: нужен useWindowDimensions.
  2. Ошибкастрока 4
    color у View ничего не делает, текст его не наследует. Тень через shadowOpacity работает только на iOS, на Android нужен elevation или boxShadow.
  3. Производительностьстрока 4
    Инлайновые объекты стилей создаются в каждом рендере. Вынести в StyleSheet.create.
  4. Ошибкастрока 5
    У удалённой картинки нет размеров: она не отобразится. Нужны width/height или aspectRatio.
  5. Ошибкастрока 6
    При discount === 0 выражение 0 && ... отрендерит 0 вне Text и упадёт. Использовать явное сравнение product.discount > 0 ? ... : null.
  6. Ошибкастрока 7
    Строка внутри View: ошибка «Text strings must be rendered within a <Text>».
  7. Стильстрока 8
    Кнопка высотой 24 слишком мала для пальца, нет accessibilityRole и подписи. Минимум около 44 точек или hitSlop.

Разбор

Классические ошибки перехода с веба: текст вне Text, ожидание наследования стилей, && с числом, картинка без размеров. Плюс платформенные тени и снимок размеров вместо хука.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.