логотип PurpleSchool
логотип PurpleSchool

Отображение webview в приложении на React Native

Автор

Олег Марков

Введение

В современном мобильном развитии часто возникает задача интеграции веб-контента — например, страниц сайта, встроенных платежей или микросервисов — непосредственно в мобильное приложение. Именно для решения этой задачи был создан webview. В приложениях на React Native webview позволяет отображать веб-страницы и даже сложные веб-приложения внутри мобильного интерфейса, обеспечивая гибкость и расширяя функциональность без написания большого объема нативного кода.

React Native изначально не включает webview в стандартной поставке. Для работы с webview вам потребуется отдельная библиотека. Давайте рассмотрим, как добавить и настроить компонент webview в вашем проекте на React Native, научимся управлять его поведением, разберём возможные сценарии обмена данными между JavaScript-кодом в webview и основным приложением, рассмотрим обработку ошибок, работу с различными платформами, вопросы безопасности и производительности, а также уделим внимание типичным ситуациям, с которыми сталкиваются разработчики.

Установка и базовая настройка WebView

В современных проектах на React Native для webview используется самостоятельная библиотека react-native-webview, поддерживаемая сообществом.

WebView позволяет отображать веб-страницы внутри вашего React Native приложения. Это полезно для интеграции существующего веб-контента, отображения интерактивных карт или внедрения сторонних сервисов. Чтобы эффективно использовать WebView, необходимо понимать его возможности и ограничения, а также уметь взаимодействовать с веб-контентом из React Native кода. Если вы хотите детально разобраться в отображении WebView в React Native и создавать приложения, которые легко интегрируют веб-контент — приходите на наш большой курс React Native и Expo Router. На курсе 184 уроков и 11 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Установка библиотеки

Для интеграции webview выполните установку через npm или yarn:

npm install react-native-webview
# или
yarn add react-native-webview

На iOS потребуется выполнить linking и сборку pods:

npx pod-install ios

Если вы используете Expo, начиная с SDK 41 webview доступен через пакет expo install:

expo install react-native-webview

Минимальная реализация webview

Вот как выглядит самый простой пример использования webview:

import React from 'react';
import { SafeAreaView, StyleSheet } from 'react-native';
import { WebView } from 'react-native-webview';

const MyWebViewScreen = () => {
  return (
    <SafeAreaView style={styles.container}>
      <WebView
        source={{ uri: 'https://reactnative.dev' }} // Здесь задается URL сайта
        style={styles.webview}
      />
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1 },
  webview: { flex: 1 }
});

export default MyWebViewScreen;

Здесь мы добавляем компонент WebView на весь экран. В параметре source указываем объект с ключом uri и ссылкой на нужную страницу.

Передача локальных HTML-страниц в webview

Вместо удаленного URL вы можете отображать и локальные HTML-файлы:

Подключение локального файла (Android & iOS)

Для этого используется параметр source с ключом require или метод чтения файла (с учетом особенностей платформы).

<WebView
  originWhitelist={['*']}
  source={require('./assets/my-page.html')} // файл должен лежать в каталоге проекта
/>

Для гибкой работы с локальным HTML-кодом используйте свойство source={{ html: '<h1>Hello from WebView!</h1>' }}:

<WebView
  source={{ html: '<h1>Hello from WebView!</h1>' }}
/>

Взаимодействие между приложением и содержимым webview

Ошибочно полагать, что webview — это только "читалка" страницы. Вы можете организовать двусторонний обмен данными:

Отправка данных из webview в React Native

Для этого используется функция window.ReactNativeWebView.postMessage внутри веб-страницы.

Пример: отправка сообщения

<WebView
  source={{ html: `
    <button onclick="window.ReactNativeWebView.postMessage('Hello from HTML')">Send</button>
  `}}
  onMessage={event => {
    // здесь обрабатываем сообщение из webview
    console.log('Получено сообщение:', event.nativeEvent.data);
  }}
/>

В этом примере при нажатии на кнопку вызывается postMessage, а в коде React Native ловим событие через onMessage и обрабатываем его.

Отправка данных из React Native в страницу webview

Для этого используйте метод injectJavaScript или свойство injectedJavaScript.

Исполнение кода на стороне webview

import React, { useRef } from 'react';
import { WebView } from 'react-native-webview';
import { Button } from 'react-native';

const SendDataExample = () => {
  const webviewRef = useRef(null);

  const sendData = () => {
    // Здесь отправляем JavaScript-код во внутренний контекст webview
    webviewRef.current.injectJavaScript(`
      document.body.style.backgroundColor = "yellow"; //Меняем цвет фона
      true; // требуется для корректного закрытия промиса после выполнения кода
    `);
  };

  return (
    <>
      <WebView
        ref={webviewRef}
        source={{ html: '<h2>Изменить фон страницы</h2>' }}
      />
      <Button title="Поменять фон" onPress={sendData}/>
    </>
  );
};

Как видите, с помощью injectJavaScript вы напрямую управляете поведением страницы.

Использование injectedJavaScript

Если нужно выполнить JavaScript при инициализации страницы, используйте props injectedJavaScript:

<WebView
  source={{ uri: 'https://example.com' }}
  injectedJavaScript={`alert('WebView загружена!'); true;`}
  onLoad={() => console.log('Страница загружена')}
/>

Навигация и контроль переходов

Чтобы управлять переходами внутри webview и предотвратить открытия сторонних сайтов:

Отслеживание переходов

Используйте событие onNavigationStateChange:

<WebView
  source={{ uri: 'https://reactnative.dev' }}
  onNavigationStateChange={navState => {
    // navState.url — текущий url
    console.log('Сейчас открыт:', navState.url);
  }}
/>

Открытие некоторых ссылок во внешнем браузере

Пример: открывать внешние сайты вне приложения.

import { Linking } from 'react-native';

<WebView
  source={{ uri: 'https://my-internal-page.com' }}
  onShouldStartLoadWithRequest={request => {
    // Проверяем, что ссылка не внутренняя
    if (!request.url.startsWith('https://my-internal-page.com')) {
      Linking.openURL(request.url); // Открываем ссылку в внешнем браузере
      return false; // Запрещаем переход внутри webview
    }
    return true;
  }}
/>

Управление загрузкой, обработка ошибок и кэширование

Загрузка и индикатор

Для отслеживания статуса загрузки используйте события onLoadStart, onLoadEnd, onLoad:

<WebView
  source={{ uri: 'https://example.com' }}
  onLoadStart={() => console.log('Начало загрузки')}
  onLoadEnd={() => console.log('Загрузка завершена')}
  onError={syntheticEvent => {
    const { nativeEvent } = syntheticEvent;
    console.warn('Ошибка загрузки: ', nativeEvent);
  }}
/>

Это удобно для показа loader'а на экране во время загрузки страницы.

Очистка кэша

Можно принудительно очистить кэш webview:

import { WebView } from 'react-native-webview';

<WebView
  source={{ uri: 'https://example.com' }}
  cacheEnabled={false} // отключить кэш по необходимости
/>

Для более глубокой очистки потребуется использование нативного кода.

Настройка безопасности

WebView как механизм наследует многие риски обычных браузеров. Обязательно учитывайте следующие моменты:

  • Используйте только надежные источники (следите за свойствами originWhitelist, позволяет явно задать разрешенные домены).
  • Отключите выполнение сторонних скриптов, если это не требуется (javaScriptEnabled={false}).
  • Не подключайте неизвестные внешние ресурсы во встроенных страницах.
  • Если есть доступ к Cookie или файловой системе, ограничьте его минимально необходимым уровнем.

Пример ограничения доменов:

<WebView
  source={{ uri: 'https://secure-site.com' }}
  originWhitelist={['https://secure-site.com']}
/>

Особенности отображения на Android и iOS

Отличия в поведении

  • iOS: webview работает на WKWebView (начиная с RNWebview v6), поддерживает features iOS Safari, но не поддерживает Flash, old-style plugins.
  • Android: построен на системной реализации WebView, может отличаться в зависимости от версии системы.

Не всем props доступны обеим платформам!

Например, allowsInlineMediaPlayback работает только на iOS, а onContentProcessDidTerminate — специфичен для iOS.

Использование пользовательских User-Agent

<WebView
  source={{ uri: 'https://your-page.com' }}
  userAgent="MyCustomAgent/1.0"
/>

Управление состоянием

На Android webview иногда не обновляет содержимое при возвращении на экран — используйте props key или принудительный обновления через state.

Производительность и оптимизация

  • По возможности минимизируйте использование сторонних скриптов внутри webview.
  • Не забывайте закрывать (размонтировать) webview после использования.
  • Оцените, нужен ли webview на каждом экране, или можно использовать нативные экраны с REST API для специфических задач.

Отображение WebView - это полезный инструмент в разработке современного React Native приложения. Однако, для создания полноценного приложения необходимо освоить множество других технологий и подходов, включая работу с UI, данными и нативными функциями. Курс React Native и Expo Router поможет вам в этом. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в мир React Native прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Как ограничить скролл внутри webview?

Используйте свойство scrollEnabled={false} — это запретит пользователю листать содержимое webview. На некоторых версиях Android/WKWebView нужно также внутри HTML задавать CSS overflow:hidden для body.

Как загрузить PDF внутри webview?

В большинстве случаев для PDF рекомендуется использовать обычное открытие ссылки в браузере, либо использовать сторонние модули (react-native-pdf). Для быстрой проверки в webview хватит передачи url на PDF (многие мобильные webview поддерживают просмотр PDF-файлов по url).

Ошибка: webview не отображает изображение с внешнего ресурса

Проверьте HTTPS-протокол: многие webview блокируют небезопасные соединения по HTTP по умолчанию, особенно в iOS. Используйте https-сервер, либо настройте app transport security (ATS) в Info.plist на iOS.

Как удалить cookies в webview?

В Android используйте import { CookieManager } from '@react-native-cookies/cookies'; — далее вызовите CookieManager.clearAll(). На iOS потребуется использовать WKWebViewConfiguration, специальные методы очистки кук или заменить webview на новую с другим session.

Как реализовать автологин пользователя во встраиваемом webview?

Передавайте токен (или сессионную куку) через injectedJavaScript или через props sharedCookiesEnabled={true} (iOS) / thirdPartyCookiesEnabled={true} (Android); для более продвинутых сценариев генерируйте ссылку с включенной авторизацией либо интегрируйте механизм SSO по вашему API.

Интеграция Typescript в React NativeСтрелочка вправо

Постройте личный план изучения React-native до уровня Middle — бесплатно!

React-native — часть карты развития Mobile

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React-native

Работа со ScrollView в React NativeРабота с видео в React NativeКак реализовать аудиоплеер на React NativeНастройка и использование input и textinput в React NativeИнтеграция видео плеера в приложение на React NativeИспользование выпадающих списков в React NativeСоздание и настройка native module на React NativeКак создать модальные окна в React NativeРабота с изображениями в React NativeОтображение списков данных в React NativeГайд по файловой системе в React NativeИнтеграция камеры в приложение на React NativeСоздание интерактивных кнопок в React Native
Как использовать векторные иконки в React Native5 популярных библиотек UI компонентов React NativeСоздание и использование tabs в React NativeРуководство по стилизации компонентов в React NativeОптимизация переходов между экранами в React NativeАдаптация safe area context на React NativeОбзор библиотек для навигации в React NativeСоздание сложных анимаций (reanimated) на React NativeИспользование библиотеки стилей Paper в React NativeРуководство по navigation в React NativeОптимизация отображения списков в React NativeКак реализовать linking на React NativeГайд по UI-китам для React NativeГде искать elements для приложения на React NativeРабота с цветами в React Native
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React Native и Expo Router

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы JavaScript

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий