Олег Марков
Работа с изображениями в React Native
Введение
Работа с изображениями - один из важных аспектов при разработке мобильных приложений на React Native. Картинки делают интерфейс привлекательнее, помогают наполнить контент, реализовать визуальные сценарии, а иногда вообще являются основным элементом взаимодействия пользователя с приложением.
В этой статье мы разберем все ключевые моменты, связанные с использованием изображений в React Native: как подключать локальные и удаленные изображения, менять их размер, оптимизировать, обрабатывать ошибки загрузки, делать кэширование и добавлять кастомные компоненты для работы с изображениями. Я покажу вам практические примеры кода и обращу внимание на детали, которые помогут избежать распространённых проблем.
Основы использования изображений
Компонент Image
В React Native для вывода изображений используется компонент Image
. Он есть во всех проектах по умолчанию, не требует отдельной установки. Давайте посмотрим, как его можно использовать:
import { Image } from 'react-native';
// Так мы отображаем картинку из локального каталога
<Image
source={require('./assets/logo.png')}
style={{ width: 100, height: 100 }}
/>
// Здесь картинка загружается из сети
<Image
source={{ uri: 'https://reactnative.dev/img/logo-og.png' }}
style={{ width: 200, height: 80 }}
/>
- Свойство
source
отвечает за путь к картинке. - Свойство
style
обязательно должно содержать размеры (ширина и высота). Без них компонент не увидит картинки.
Работа с изображениями в React Native требует внимания к оптимизации, масштабированию и форматам, чтобы обеспечить высокую производительность и качественное отображение на разных устройствах. Важно уметь правильно загружать изображения, кэшировать их и использовать различные техники для уменьшения размера файлов без потери качества. Также, для работы с графикой может потребоваться понимание таких тем, как анимация и нативные возможности. Если вы хотите детальнее погрузиться в работу с изображениями и другими аспектами React Native разработки, — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.
Работа с локальными изображениями
Когда вы хотите добавить картинку, которая будет идти вместе с приложением, используйте команду require
. Файл должен лежать внутри вашего проекта, например, в папке assets
.
<Image
source={require('./assets/photo.jpg')} // путь относительно текущего файла
style={{ width: 150, height: 150 }}
/>
- Такой подход удобен, когда картинки статичны и не меняются.
- Изображения, подключённые через
require
, включаются в сборку приложения и не зависят от интернета.
Загрузка изображений из интернета
Часто нужно показывать картинки из внешних источников через ссылку (url
). Тогда source будет объект с полем uri:
<Image
source={{ uri: 'https://example.com/image1.png' }}
style={{ width: 200, height: 150 }}
/>
- По умолчанию React Native загружает изображение с сети и отображает его.
- Не забывайте задавать размеры в style. Без них картинка не появится!
Работа с форматами изображений
React Native поддерживает форматы PNG, JPG и GIF. С SVG ситуация сложнее: для SVG требуется подключать дополнительные библиотеки (например, react-native-svg
), так как стандартный компонент Image не умеет работать с этим форматом.
npm install react-native-svg
import SvgUri from 'react-native-svg-uri';
<SvgUri
width="100"
height="100"
source={{uri:'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg'}}
/>
Обратите внимание: для SVG это уже другой компонент, и у него свои особенности.
Размеры, стилизация и адаптация изображений
Явное указание размеров
Проще всего задать вместе с компонентом:
<Image
source={require('./assets/icon.png')}
style={{ width: 72, height: 72 }}
/>
- Не задав размеры, вы столкнётесь с пустым местом на экране.
Масштабирование с помощью resizeMode
У компонента Image есть свойство resizeMode
, которое определяет, как масштабируется изображение в заданных границах:
cover
— масштабирует, чтобы заполнить всё пространство (часть картинки может обрезаться).contain
— вписывает полностью в доступные размеры (могут остаться пустые области).stretch
— растягивает до размеров.center
— размещает картинку по центру без масштабирования.repeat
— фон из повторяющихся изображений (работает не во всех платформах).
<Image
source={{ uri: 'https://example.com/photo.jpg' }}
style={{ width: 300, height: 100 }}
resizeMode="contain" // попробуйте поменять на cover, stretch и посмотрите отличия
/>
Округление, рамки и стили
Стилизация работает так же, как с любым другим View или Text:
<Image
source={{ uri: 'https://example.com/user.jpg' }}
style={{
width: 120,
height: 120,
borderRadius: 60, // делает изображение круглым
borderWidth: 2,
borderColor: 'tomato',
}}
/>
- Если хотите сделать идеально круглым — ширина и высота должны совпадать, а borderRadius равняться половине ширины/высоты.
Работа с прогрессом загрузки, ошибками и плейсхолдерами
Отображение плейсхолдера пока изображение загружается
Стандартный Image не предоставляет встроенных событий для отслеживания статуса загрузки. Но вы можете реализовать подобное поведение при помощи композиции нескольких компонентов:
import React, { useState } from 'react';
import { View, Image, ActivityIndicator, StyleSheet } from 'react-native';
const RemoteImage = ({ uri, style }) => {
const [loading, setLoading] = useState(true);
return (
<View style={style}>
{loading && (
<ActivityIndicator
style={StyleSheet.absoluteFill}
size="large"
color="#888"
/>
)}
<Image
source={{ uri }}
style={StyleSheet.absoluteFill}
onLoadEnd={() => setLoading(false)} // скрываем спиннер после загрузки
/>
</View>
);
};
- Здесь мы показываем индикатор загрузки пока картинка скачивается.
- Пример, как это выглядит на практике.
Обработка ошибок загрузки изображения
Если изображение не грузится (например, битая ссылка), используйте событие onError
, чтобы подменить изображение или показать ошибку:
import React, { useState } from 'react';
import { Image } from 'react-native';
const FallbackImage = ({ uri, fallbackSource, style }) => {
const [error, setError] = useState(false);
return (
<Image
source={error ? fallbackSource : { uri }}
style={style}
onError={() => setError(true)} // меняем source на запасной, если ошибка загрузки
/>
);
};
- Это позволит не показывать пустое место, если изображение не загрузилось.
Оптимизация и кэширование изображений
Почему кэширование важно
Картинки из сети могут быть большими и долго грузиться. Без кэширования пользователю придется скачивать их каждый раз заново. В стандартном компоненте Image Android и iOS умеют кэшировать изображения автоматически, но контроль над этим ограничен.
Если задача требует контроля кэша или показа изображений в офлайн-режиме — лучше использовать сторонние библиотеки.
Использование react-native-fast-image
Одна из самых популярных библиотек для оптимизации работы с изображениями — react-native-fast-image
. Она дает:
- Улучшенное кэширование
- Поддержку прогресса загрузки
- Опцию для выбор способа кэширования
Установка:
npm install react-native-fast-image
Использование:
import FastImage from 'react-native-fast-image';
<FastImage
style={{ width: 200, height: 200 }}
source={{
uri: 'https://example.com/image.jpg',
priority: FastImage.priority.high,
cache: FastImage.cacheControl.immutable, // всегда использовать оригинальное изображение из кэша
}}
resizeMode={FastImage.resizeMode.cover}
/>
- FastImage полностью повторяет интерфейс стандартного компонента Image с дополнительными возможностями.
Реализация интерактивных и анимированных изображений
Зум, скроллинг и другие интерактивные эффекты
Если вам нужно, чтобы пользователь мог масштабировать изображение (например, картинка товара или аватар) — используйте готовые пакеты типа react-native-image-zoom-viewer
или оборачивайте Image в ScrollView с опцией zoom:
import { ScrollView, Image } from 'react-native';
// картинка, которую можно масштабировать
<ScrollView
minimumZoomScale={1}
maximumZoomScale={3}
contentContainerStyle={{ alignItems: 'center', justifyContent: 'center' }}
>
<Image
source={{ uri: 'https://example.com/large-photo.png' }}
style={{ width: 300, height: 300 }}
/>
</ScrollView>
Анимации изображений
Для анимации появления изображения используйте Animated API:
import React, { useRef, useEffect } from 'react';
import { Animated, Image } from 'react-native';
const FadeInImage = ({ source, style }) => {
const opacity = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(opacity, {
toValue: 1,
duration: 700,
useNativeDriver: true,
}).start();
}, []);
return (
<Animated.Image
source={source}
style={[style, { opacity }]} // анимация появляется плавно
/>
);
};
- Этот пример показывает, как реализовать плавное появление картинки.
Платформенные особенности и ограничения
Ограничения Android и iOS
- На Android поддерживается большая часть функциональности Image, кроме некоторых режимов resizeMode.
- iOS и Android кэшируют изображения по-разному — это может влиять на работу с сетевыми картинками, когда вы ожидаете одинакового поведения на обеих платформах.
- На Android иногда возникают проблемы с отображением больших изображений — приложение может упасть из-за нехватки памяти.
Работа с большим количеством или большими изображениями
Если у вас список из множества картинок (например, галерея), обязательно используйте FlatList или SectionList с правильным использованием props like removeClippedSubviews
и оптимизируйте отображение:
import { FlatList, Image } from 'react-native';
const images = [
{ id: '1', uri: 'https://example.com/ph1.png' },
{ id: '2', uri: 'https://example.com/ph2.png' },
// ...
];
<FlatList
data={images}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Image source={{ uri: item.uri }} style={{ width: 100, height: 100 }} />
)}
removeClippedSubviews
/>
- FlatList рендерит только видимые элементы, экономя память.
Продвинутые возможности
Динамическая подгрузка изображений
Когда вы знаете только имя файла или ссылку и хотите динамически подгружать изображения:
- Локальные изображения через require не поддерживают динамическую подгрузку. Вам нужно заранее импортировать путь или использовать switch/case для выбора нужного require.
- Для работы с массивами фото из сети проще использовать url.
Обработка EXIF, ориентация фотографий
Для чтения EXIF-данных (например, ориентации фото из камеры) можно использовать библиотеку react-native-exif
или react-native-image-picker
. Это позволит корректно отображать фотографии, сделанные на устройствах с разной ориентацией камеры.
Использование градиентов поверх изображений
Можно легко добавить градиент поверх картинки, используя пакет react-native-linear-gradient
и абсолютное позиционирование:
import LinearGradient from 'react-native-linear-gradient';
<View style={{ width: 200, height: 200 }}>
<Image
source={{ uri: 'https://example.com/photo.jpg' }}
style={{ width: 200, height: 200, position: 'absolute' }}
/>
<LinearGradient
colors={['transparent', 'rgba(0,0,0,0.5)']}
style={{ width: 200, height: 200, position: 'absolute' }}
/>
</View>
- Такой подход часто применяют для затемнения нижней части карточек с текстом.
Заключение
Работа с изображениями в React Native включает множество аспектов: от базового вывода и задания размеров до кастомизации, оптимизации загрузки, обработки ошибок и обеспечения высокого UX. Важно понимать, как выбирается источник изображения, как задаются его размеры, как показаны плейсхолдеры и что делать в случае ошибки. Сторонние библиотеки помогают закрыть большинство сложных случаев (кэширование, SVG, прогресс загрузки). Обязательно учитывайте разницу между платформами и уделяйте внимание производительности, особенно если работаете с большим количеством картинок.
Оптимизация изображений — лишь одна из многих задач при разработке React Native приложений. Для создания профессионального и удобного приложения необходимо уметь создавать компоненты, управлять навигацией и состоянием, а также работать с нативными модулями. На нашем курсе React Native и Expo Router вы найдете все необходимые знания для освоения React Native разработки. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Вопрос 1: Как динамически выводить локальные картинки по имени файла из массива?
Ответ: Для локальных файлов через require нельзя использовать строковые пути. Используйте объект с именами файлов и заранее импортированными require-ссылками.
const images = {
'user1': require('./assets/user1.jpg'),
'user2': require('./assets/user2.jpg'),
};
// images[name] теперь можно передавать в source
Вопрос 2: Как обрабатывать клики по изображению?
Ответ: Оберните Image в TouchableOpacity или TouchableWithoutFeedback и добавьте обработчик onPress.
import { TouchableOpacity, Image } from 'react-native';
<TouchableOpacity onPress={() => alert('Картинка нажата!')}>
<Image source={...} style={{width: 100, height: 100}} />
</TouchableOpacity>
Вопрос 3: Почему gif-анимации иногда не работают на Android?
Ответ: Для анимации gif на Android требуется установка dependency Fresco или использование сторонних библиотек вроде react-native-fast-image.
Вопрос 4: Как получить реальный размер картинки до загрузки (например, чтобы правильно рассчитать layout)?
Ответ: Используйте метод Image.getSize(uri, success, failure):
Image.getSize('https://example.com/photo.jpg', (width, height) => {
// width и height — реальные размеры
})
Вопрос 5: Можно ли сжать или уменьшить размеры изображения перед загрузкой/отправкой на сервер?
Ответ: Используйте библиотеки типа react-native-image-resizer или react-native-image-crop-picker. Они позволяют обрезать и изменять размер изображений на устройстве до отправки.
Постройте личный план изучения React-native до уровня Middle — бесплатно!
React-native — часть карты развития Mobile
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по React-native
Лучшие курсы по теме

React Native и Expo Router
Антон Ларичев
Основы JavaScript
Антон Ларичев