Выбор ответа Senior Компоненты и стили обновлено

React Native: инлайновые стили и memo

Вопрос

Строка списка обёрнута в memo, но перерисовывается при каждом рендере родителя. Почему?

const Row = memo(function Row({ item, style, onPress }: RowProps) {
  return <Pressable style={style} onPress={onPress}><Text>{item.title}</Text></Pressable>;
});

function List({ items, select }: ListProps) {
  return items.map((item) => (
    <Row key={item.id} item={item} style={{ marginTop: 8 }} onPress={() => select(item.id)} />
  ));
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Каждый рендер передаёт новые объект стиля и функцию, memo видит изменения. memo сравнивает пропсы по ссылке.

Варианты ответа

  1. memo не работает в React Native, он есть только в React DOM для браузера
  2. Объекты StyleSheet нельзя передавать в memo-компоненты, это ломает сравнение
  3. Компонент перерисовывается из-за key: React пересоздаёт элемент при каждом рендере
  4. Каждый рендер передаёт новые объект стиля и функцию, memo видит измененияправильный ответ

Разбор

memo сравнивает пропсы по ссылке. Литерал { marginTop: 8 } и стрелка () => select(item.id) создаются заново в каждом рендере, поэтому ссылки разные. Решение: стили в StyleSheet.create вне компонента, колбэк через useCallback (и передача id отдельным пропсом). memo в RN работает так же, как в вебе, а стабильный key не вызывает перерисовок.

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

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