25 понятных туториалов для изучения React Native


Оглавление (нажмите, чтобы открыть):

Пишем полноценное приложение на React с нуля за час

В этой статье вы познакомитесь с React — библиотекой для создания пользовательских интерфейсов. React появился в 2013 году и достаточно быстро стал популярным среди разработчиков. Сегодня в работе над веб-приложениями его используют Facebook, Instagram, Trello, AirBnb, PayPal. С помощью этой статьи мы сможем написать приложение прогноза погоды: от установки с помощью create-react-app (проект на GitHub) до подключения API и стилей bootswatch.

Прим. перев. Если вы начинаете изучение React, вам также стоит прочитать наш материал, в котором разработчик делится советами по использованию этой библиотеки.

Этот материал был написан для воркшопа Open Source Dev Garage, прошедшего в рамках конференции разработчиков F8 2020. Чтобы лучше разобраться в том, как написать это приложение, посмотрите 48-минутное видео или следуйте письменным инструкциям в этом руководстве.

Просмотрев семинар или изучив руководство, вы создадите простое приложение прогноза погоды:

Создайте ваше первое приложение

Прежде всего вам понадобится node.js и редактор кода, например, Atom.

Откроем терминал и установим create-react-app :

Примечание: Пользователям Linux или MacOS, возможно, потребуется дополнительно ввести команду sudo перед npm install -g .

Начнем создавать наше приложение прогноза погоды:

Данной командой мы установим набор инструментов, которые помогут создать наше React-приложение. По завершении установки мы сможем запустить приложение командами:

Новое приложение автоматически откроется в браузере!

Свойства и компоненты

Давайте взглянем на приложение, которое create-react-app создал автоматически. В редакторе кода откроем weather/src/App.js :

Наше приложение состоит из одного компонента, где функция render() является его главной составляющей. Напишите какой-нибудь текст, сохраните изменения и посмотрите, как приложение автоматически применит их!

15–16 ноября, Минск, 133–390 br

Теперь создадим новый компонент WeatherDisplay . Так как функция render() — это «сердце» компонента, то именно она определяет, что будет отображено. Для начала создадим тег с каким-нибудь текстом внутри:

Изменим компонент App , чтобы отобразить наш WeatherDisplay :

Как видите, мы передали данные, которые обозначили переменной zip , в компонент WeatherDisplay . Они называются свойствами (props). Мы можем модифицировать наш компонент для отображения передаваемых данных:

Где-нибудь в начале файла добавим несколько городов, для которых мы хотели бы отобразить погоду:

Обновим render() в компоненте App , в котором, перебирая массив PLACES , создадим тег button для каждого города:

Из массива данных мы создадим набор элементов button и назначим свойство key для каждого, чтобы React знал последовательность элементов в массиве.

Здесь также есть обработчик событий onClick , который при нажатии будет выводить сообщение в консоль браузера. Открыв панель разработчика в браузере, вы можете увидеть логи событий. Ваше приложение должно выглядеть так:

На этом этапе файл App.js должен выглядеть так.

Состояние

Мы хотим, чтобы в приложении была возможность переключаться между местами, поэтому мы можем использовать состояние ( state ) для хранения данных в компоненте App .

Сначала давайте добавим функцию-конструктор, в которой будет использоваться super() , а затем установим начальное состояние this.state :

Функция render() может брать данные из this.state при составлении пользовательского интерфейса. Для этого мы можем использовать метод setState компонента React, который меняет состояние и перезапускает функцию render() , чтобы изменить пользовательский интерфейс.

Применим this.state и this.setState в нашем компоненте App :

На этом этапе файл App.js должен выглядеть так.

Жизненный цикл компонентов и выборка данных

Иногда нам нужно добавить императивный код (React-код обычно декларативен), который вызывается в определенное время жизни компонента. Методы жизненного цикла позволяют нам написать дополнительный код как раз для таких случаев.

В этом примере мы хотим вызвать API, когда компонент загрузится на экране, для этого добавим код в componentDidMount . Обновим компонент WeatherDisplay :

Улучшим вывод render() для красивого вывода данных:

На этом этапе файл App.js должен выглядеть так.

Установка компонентов

Наше приложение всё еще выглядит не очень красиво. Можно исправить это, добавив className (из стилей CSS) в свойства div или установив соответствующую библиотеку с помощью npm .

Bootstrap — популярный набор инструментов для стилизации пользовательского интерфейса в HTML и CSS. Установим его вместе с react-bootstrap , который предоставляет компоненты React для bootstrap :

Импортируем стили из bootstrap в начале файла:

Далее импортируем из react-bootstrap компоненты, которые мы хотим использовать. Их можно найти на сайте react-bootstrap:

Заменим теги в компоненте App , чтобы вывести компоненты bootstrap :

Теперь наше приложение выглядит привлекательнее, но будет здорово, если мы добавим что-то от себя. Для этого установим bootswatch :

Выберите подходящее оформление на сайте bootswatch и установите его, заменив bootstrap . В нашем примере мы используем тему journal:

Окончательный вид нашего приложения:

Развертывание (дополнительный материал)

Прежде всего опубликуйте ваш код на Github, затем перейдите в ваш репозиторий и откройте файл ReadMe, в котором вы найдете инструкцию по развертыванию приложения на различных популярных сервисах.

Одним из таких сервисов является Netlify, особенно в случае, когда вы хотите использовать механизм “непрерывного развертывания”.

Как стать разработчиком React Native в 2020

Если вы посмотрите на результаты The State of JavaScript 2020, то найдёте много интересной информации.

Кое-что сразу бросается в глаза — очень много людей желают изучить React Native.

И это радует глаз! Последний год я обучал людей созданию мобильных приложений с помощью React Native. Начиная с команд разработчиков, которые стремились развивать существущие проекты, расширяя поддерживаемые платформы до мобильных устройств, заканчивая людьми из Африки и Индии, которые искали способ улучшить уровень жизни их сообществ с помощью различных мобильных приложений.

Часть времени приходилось уделять ответам на письма людей, которые только начинают свой путь, и пытаются определить лучший способ изучения React Native.

Не малую часть моего времени занимают — ответы на ваши письма. Какой вопрос мне задают чаще всего? Каким способом “лучше” изучать React Native? На самом деле нет единственного пути, но вот, что я отвечал людям, которые собираются стать React Native разработчиками. Я надеюсь это поможет и вам тоже.

Рекомендации

Перед тем как погрузиться в тактические детали превращения в React Native разработчика, я хочу дать вам пару общих советов по самообучению. Я понял, что люди успешно учатся новым вещам, если уделяют достаточно времени на обучение.

Я понимаю, что все мы постоянно заняты, но выполняя минимальные действия — мы уже обучаемся.


Избегайте шума

В данный момент вы читаете статью на Medium. Вы нашли её через Google или любым другим способом. Это значит, что скорее всего, вы поглощаете много информации о технологиях.

Это здорово! Мир технологий, в котором мы живём, растёт и развивается.

Но это может быть очень утомительным, особенно когда ты только начинаешь. Мой совет будет таким. Как только вы закончите читать этот пост и составите план обучения — держите себя в руках!

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

Составьте план и придерживайтесь его! Боритесь с боязнью отстать от мира технологий. Вы всегда успеете догнать его, как только получите фундаментальные знания.

Не завышайте своих ожиданий

Я часто получаю письма, в которых люди жалуются на то, что у них не получается интегрировать сложные пакеты в свои проекты. Но должно же получиться — это же моё прогрессивное и многофункциональное приложение!

Я понимаю, что вы уже хотите погрузиться в разработку своего приложения прямо сейчас. Но это не будет лучшим началом. Такой подход очень разочаровывает, так как вы будете развиваться. Для вас будет мучительным открывать ваше приложение через неделю, и видеть, что что-то написано “неправильно”. Теперь вам нужно проходить всё заново, и исправлять все недоработки.

Изучайте одну концепцию / один модуль / одну технику за раз. Делайте это в изолированной от проекта среде (песочнице).

Как только вы разберётесь с чем-либо в песочнице, переносите это в свой проект. Таким образом вы станете счастливее, ваш код станет чище, и вы начнёте лучше понимать, что к чему.

Распланируйте время

Вы заняты. Я занят. Мы все очень заняты. Но мы всегда находим время для важных вещей. Таких, как поход к доктору, или свидание, или встреча с вашим боссом / инвестором.

Суть в том, что вы даёте обещание. Вы добавляете его в свой график, и придерживаетесь его.

Обучение и инвестирование в самого себя — это так же важно, и заслуживает быть запланированным.

Но у меня совсем нет времени!

Найдите хотя бы 5 минут — я знаю, вы можете. Выделите 5 минут на каждый день недели. Как только привыкнете — увеличьте время до 10 минут. Как только это станет комфортным — увеличьте до 15 минут.

Суть в том, чтобы иметь это в плане на день, и придерживаться его. Поверьте мне, это работает.

Моё время на обучения — это 30 минут перед ланчем, и 15–30 минут после ужина.

Создайте план обучения

Мы уже обсудили это, но нам правда нужно пройтись по этой теме ещё раз. Время потраченное на создание плана — полностью окупается. Вы уже делаете это для многих вещей в своей жизни — так почему бы не составить план для изучения React Native?

Возвращаясь к первой рекомендации — если у вас нет плана, рано или поздно вы осознаете, что бессмысленно гоняетесь за свежими технологиями, так и не доведя хотя бы одну из них до логического конца. Сейчас не время для этого. Пришло время составлять план!

Вот, как я предлагаю сделать это. Посмотрите на список ресурсов ниже, просмотрите материалы, которые они предлагают, и добавьте нужные в свой план. Сконцентрируйтесь на них, и пока не освоите все пункты из списка, не распыляйте своё внимание на что-либо еще.

Создание плана обучения может показаться неким барьером, или чем-то, что сложно совершить. Но это совершенно не так! И чтобы избежать рассеянности, я подготовил такой план для вас к этому посту. Скачать можно здесь (на английском).

Не останавливайтесь на потреблении

Я заметил, что многие студенты моих курсов подвержены этому недугу. Они смотрят видео, и на этом их обучение заканчивается. Пишите код сами, или повторяйте то, что я сделал в видео, как только закончите просмотр.

Потребляя и производя — вот как мы достигаем высшего уровня мастерства и настоящего понимания того, что мы изучаем. Вы сталкиваетесь с проблемами, которые вам нужно решить. Вы интересуетесь, почему это сделано именно таким образом? Следуя этому совету — вы вырабатываете “мышечную память”.

Не останавливайтесь на потреблении, создавайте.

�� 25 понятных туториалов для изучения React Native. #[email protected] #[email protected]

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

25 понятных туториалов для изучения React Native

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

Комментарии (4)

Павел Кылосов

История о том как возненавидеть Facebook и начать пить.

Рахма Меджидов

Павел, как раз то, что я ищу

Сулейман Сулейманов

Кто знает как выйти из Facebook ?

Микола Сидоренко

Сулейман, Разлейте на системный блок чашечку кофе или ударте его с правого сбока так, чтобы вмятина появилась. Можно ещё разбить монитор.

О проекте

Данный сайт является агрегатором контента из популярных социальных сетей. Добавление новых материалов производится в автоматическом режиме. Администрация проекта не несет ответственности за их содержание.

Изучение с нуля и продвинутые техники React Native

Для вас выступят Full Stack Developers из компании IdeaSoft.

Откроет митап Станислав Алейник с докладом “ React Native Basics ”. Станислав расскажет об основах React Native, альтернативах, плюсах и минусах и о том, как начать его использовать в своих проектах:

“Когда я только начинал изучать React Native, было слишком много вопросов и слишком мало ответов. С чего начать? За что браться? Какие сторонние плагины использовать? Как отличить хороший плагин от плохого? Как запустить приложение на Android? iOS? Ответы приходилось искать долго, иногда с болью. Доклад призван помочь начинающим легче войти в RN и быстрее начать заниматься интересными вещами”.

Далее выступит Алексей Литвин с докладом “ TFJS + React Native ”. В рамках своего доклада Алексей ответит на вопросы: Зачем это мне? Что я могу сделать? Как я могу это сделать? Подробнее:

“В последнее время всё большее распространение во всех сферах получают алгоритмы машинного обучения. Они используются в медицине для поиска новых лекарств, в химии для поиска новых веществ с интересными свойствами, астрономами для поиска экзопланет, банками для оценки клиентов, интернет-гигантами для увеличения эффективности рекламы, разпознавание лиц, спам-фильтры и анализ контента. Сложно даже просто перечислить все современные области применения машинного обучения. Глобальный тренд не обходит стороной и мобильную разработку. В нашем докладе мы расскажем о том, какие возможности для этого предоставляет библиотека TFJS в связке с React Native”.

Артур Нехайчик выступит с темой “ AR in React Native ” и расскажет что такое AR, почему за AR будущее, как использовать AR в различных сферах, как использовать AR библиотеки в React Native приложении, и представит наглядный пример. Подробнее:
“С развитием технологий высокопроизводительные мобильные девайсы перестают быть редкостью и уже сейчас многие из телефонов способны обрабатывать большие объёмы графических данных для реализации приложений с дополненной реальностью. Такая возможность ведёт за собой большие перспективы развития современных приложений. Такой инструмент как React Native выгодно предстаёт в этом свете, поскольку позволяет писать приложения сразу для двух популярных платформ. Речь пойдёт о том, как именно можно создавать AR-приложения с помощью React Native, и о пользе использования AR в приложениях. Также будет рассмотрено небольшое демо, показывающее некоторые возможности AR-библиотеки”.

Завершит митап доклад “ Native modules in React Native ” от Владислава Харитоновича. Владислав расскажет про основы использования нативных модулей, виды нативных модулей, необходимость использования модулей и особенности использования. Подробнее:
“React Native стал одной из самых популярных во всём мире технологий для разработки приложений под мобильные платформы. Эта технология является очень перспективной и быстро развивающейся. Однако на сегодняшний день она не позволяет реализовать все задачи и нововведения мобильных операционных систем, используя только встроенный функционал, что приводит нас к необходимости написания модулей на нативных языках таких как: Objective C, Swift, Java и др. Об этом и пойдет речь в данном докладе”.

  • Станислав Алейник — Full Stack Developer, опыт разработки: 2 года. Основные интересы: React Native, Typescript, Swift, IoT
  • Алексей Литвин — Full Stack Developer, опыт разработки: 3+ года. Основные интересы: React, React Native, Typescript, ML
  • Артур Нехайчик — Full Stack Developer, опыт разработки: 4 года. Основные направления: React Native, Angular, Node.js, PHP
  • Владислава Харитонович — Full stack developer, опыт разработки: 2+ года. Основные интересы: React Native, Kotlin, C++, Node.js

О компании:
IdeaSoft занимается разработкой приложений на React Native / React и интеграцией их с алгоритмами ML/AI, IoT, AR/VR и Blockchain. Группа React Native Belarus на странице в Facebook.

Учебник: введение в React


Данный учебник не предполагает каких-либо знаний React.

Перед тем как начнём

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

Этот учебник предназначен для людей, которые желают учиться на практике. Если же вы предпочитаете изучать теоретические концепции с нуля, ознакомьтесь с нашим пошаговым руководством. Также вы можете найти пошаговое руководство и данный учебник дополняющими друг друга.

Учебник состоит из нескольких разделов:

Установка. Даст вам отправную точку, чтобы следовать учебнику.

Обзор. Познакомит вас с основами React: компонентами, свойствами и состоянием.

Завершение игры. Научит вас наиболее распространенным методам разработки в React.

Добавление Time Travel. Даст вам более глубокое понимание уникальных преимуществ React.

Вам не обязательно изучать полностью все разделы, чтобы извлечь пользу из этого учебника. Постарайтесь добраться как можно дальше — даже если это одна или две главы.

Во время изучения можно копировать и вставлять код, но мы рекомендуем набирать его вручную. Это поможет вам развить мышечную память и получить более глубокое понимание происходящего.

Что мы разрабатываем?

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

Вы можете увидеть, что именно мы будем разрабатывать здесь: Окончательный результат. Если код для вас непонятен, или если вы не знакомы с синтаксисом, не беспокойтесь! Цель учебника — помочь вам понять React и его синтаксис.

Мы рекомендуем вам ознакомиться с игрой в крестики-нолики, прежде чем продолжить обучение. Одна из особенностей, которую вы заметите, это то, что справа от игрового поля есть нумерованный список. Данный список содержит историю всех ходов, произошедших в игре, обновляясь по ходу игры.

Наш следующий шаг — произвести необходимые настройки, чтобы вы могли начать создавать игру.

Предварительные требования

Мы предполагаем, что вы немного знакомы с HTML и JavaScript. Но даже если вы переходите с другого языка программирования, вы должны быть способны понимать то, о чем идет речь в этих главах. Мы также предполагаем, что вы знакомы с такими понятиями программирования, как функции, объекты, массивы и, возможно в меньшей степени, классы.

Если вам нужно повторить JavaScript, можно использовать данное руководство (хотя лично я предпочитаю это руководство). Обратите внимание, что в данном учебнике мы используем некоторые функции ES6 — недавней версии JavaScript: функции-стрелки, классы, операторы let и const. Вы можете использовать Babel REPL, чтобы проверить, во что компилируется код ES6.

Установка

Освоить данное руководство можно двумя способами: вы можете либо писать код в своем браузере, либо настроить локальную среду разработки на своем компьютере.

1-й вариант установки

Это самый быстрый способ начать работу!

Сначала откройте этот стартовый код в новой вкладке. Новая вкладка должна отображать пустую игровую доску в крестики-нолики и код React. В этом учебнике мы будем редактировать код React.

Теперь вы можете пропустить второй вариант установки и перейти к разделу «Обзор», чтобы приступить к обзору React.

2-й вариант: локальная среда разработки

Это исключительно по желанию и совершенно не обязательно для данного учебника!

Необязательно: инструкции для разработки локально с помощью предпочитаемого вами текстового редактора.

Данная установка потребует больше времени и сил, но позволяет вам освоить учебник, используя предпочитаемый вами редактор (например WebStorm). Выполните следующие шаги:

Убедитесь, что у вас установлена последняя версия Node.js.

Удалите все файлы в папке src/ нового проекта.

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

Добавьте файл с именем index.css в папку src/ с этим кодом CSS.

Добавьте файл с именем index.js в папку src/ с этим кодом JS.

Добавьте следующие три строки в начало файла index.js в папке src/ :

Теперь, если вы запустите npm start в папке проекта и откроете http://localhost:3000 в браузере, вы должны увидеть пустое поле крестики-нолики.

Также мы рекомендуем следовать данным инструкциям, чтобы настроить подсветку синтаксиса в вашем редакторе.

Помогите, я застрял!

Если вы застряли, посетите ресурсы сообщества поддержки. В частности, Reactiflux Chat — отличный способ быстро получить помощь. Если же вы не получили ответа или зашли в тупик, пожалуйста, сообщите нам в Git о проблеме, и мы вам поможем.

Обзор

Теперь, когда вы произвели всю необходимую установку, давайте познакомимся с React!

Что такое React?

React — это декларативная, эффективная и гибкая библиотека JavaScript для создания пользовательских интерфейсов (UI). Она позволяет вам создавать сложные UI из небольших и изолированных частей кода, называемых «компонентами».

В React есть несколько разных типов компонентов, но мы начнем с подклассов React.Component :

Cкоро мы перейдем к забавным XML-подобным тегам. Мы используем компоненты, чтобы сообщить React, что именно мы хотим видеть на экране. Когда наши данные изменятся, React будет эффективно обновлять и повторно отрисовывать наши компоненты.

Мастер Йода рекомендует:  ADODB – русская документация (часть 1) PHP

Здесь ShoppingList — это класс компонента React или тип компонента React. Компонент принимает параметры, называемые props (сокращение от properties — свойства), и возвращает иерархию представлений, отображаемых с помощью метода render .

Метод render возвращает описание того, что именно вы хотите видеть на экране. React берет это описание и отображает результат. В частности, render возвращает элемент React, который и представляет собой легковесное описание того, что нужно отрисовать. Большинство разработчиков React используют специальный синтаксис под названием JSX, который облегчает написание этих структур. Синтаксис

Если вам интересно, createElement() более подробно описан в справочнике по API, но мы не будем пользоваться им в этом учебнике. Вместо него мы будем продолжать использовать JSX.

JSX включает в себя JavaScript. Вы можете поместить любые выражения JavaScript в фигурные скобки внутри JSX. Любой React элемент представляет собой объект JavaScript, который вы можете сохранить в переменной или передать куда-либо в своей программе.

Компонент ShoppingList выше отрисовывает только нативные компоненты DOM, такие как

Проверка стартового кода

Если вы собираетесь работать с учебником в своем браузере, откройте этот код в новой вкладке: стартовый код. Если вы собираетесь работать над учебником в локальной среде, откройте src/index.js в папке вашего проекта (вы уже коснулись этого файла во время установки).

Этот стартовый код является основой того, что мы строим. Мы предоставили стили CSS, так что вам нужно сосредоточиться только на изучении React и программировании игры в крестики-нолики.

Изучив код, вы заметите, что у нас есть три компонента React:

Компонент Square отображает одиночную кнопку , а Board отображает 9 квадратов. Компонент Game отображает Board со значениями чисел-заполнителей, которые мы изменим позже. В настоящее время интерактивные компоненты отсутствуют.

Передача данных с помощью props


Для эксперимента, давайте попробуем передать некоторые данные из нашего компонента Board в компонент Square .

В методе renderSquare компонента Board измените код, чтобы передать свойство с именем value в компонент Square :

Измените метод render компонента Square , чтобы он отображал это значение, поменяв на :

После: вы должны увидеть число в каждом квадрате в отрисованном выводе.

Поздравляем! Вы только что «передали свойство» из родительского компонента Board в дочерний компонент Square . Передача свойств — это то, как информация передается от родителей к потомкам в приложениях React.

Создание интерактивного компонента

Давайте заполнять компонент Square значением « X », когда мы щелкаем по нему. Сначала измените тег кнопки, который возвращается из функции render() компонента Square , следующим образом:

Если мы сейчас нажмем на Square, то должны получить предупреждение в нашем браузере.

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

Обратите внимание, что с помощью onClick = <() =>alert (‘click’)> мы передаем функцию в качестве свойства onClick . Она срабатывает только после щелчка. Пропуск () => и запись onClick = — является распространенной ошибкой, которая генерирует предупреждение каждый раз, когда компонент перерисовывается.

Следующим шагом мы хотим, чтобы компонент Square «запомнил», что на него щелкнули, и заполнил себя знаком « X ». Чтобы «запоминать» вещи, компоненты используют состояние.

Компоненты React могут иметь состояние, инициализируя this.state в своих конструкторах. Состояние this.state следует рассматривать как приватное для компонента React, в котором оно определено. Давайте сохраним текущее значение Square в this.state и изменим его при нажатии Square .

Сначала мы добавим конструктор в класс для инициализации состояния:

В классах JavaScript вам всегда нужно вызывать super при определении конструктора подкласса. Все классы компонентов React, имеющие конструктор, должны начинат его с вызова super(props) .

Теперь мы изменим метод render компонента Square для отображения значения текущего состояния при нажатии:

Замените this.props.value на this.state.value внутри тега .

Замените обработчик события () => alert() на () => this.setState() .

Поместите атрибуты className и onClick в отдельные строки для лучшей читаемости.

После этих изменений тег , возвращаемый методом render компонента Square , выглядит следующим образом:

Вызывая this.setState из обработчика onClick в методе render компонента Square , мы говорим React повторно отрисовывать этот Square при каждом нажатии на его кнопку . После обновления свойство this.state.value компонента Square будет иметь значение « X », поэтому мы увидим X на игровом поле. Если вы нажмете на любой квадрат, в нём должен появиться X .

Когда вы вызываете setState в компоненте, React автоматически обновляет и дочерние компоненты внутри него.

Инструменты разработчика

Расширение React Devtools для Chrome и Firefox позволяет вам просматривать дерево компонентов React с помощью инструментов разработчика в вашем браузере.

React DevTools позволяет вам проверять свойства и состояние ваших компонентов React.

После установки React DevTools вы можете щелкнуть правой кнопкой мыши по любому элементу на странице, нажать «Inspect», чтобы открыть инструменты разработчика. Вкладка React появится последней справа.

Однако обратите внимание, что необходимо сделать несколько дополнительных шагов, чтобы заставить его работать с CodePen:

Войдите или зарегистрируйтесь и подтвердите свой адрес электронной почты (необходим для предотвращения спама).

Нажмите кнопку «Fork».

Нажмите «Change View», а затем выберите «Debug mode».

В открывшейся новой вкладке инструменты разработчика теперь должны иметь вкладку React.

Завершение игры

Теперь у нас есть основные строительные блоки для нашей игры в крестики-нолики. Чтобы завершить игру, нам необходимо чередовать размещение « X » и « O » на доске, а также нам нужен способ определить победителя.

Поднятие состояния вверх

В настоящее время каждый компонент Square поддерживает состояние игры. Чтобы определить победителя, мы будем хранить значение каждого из 9 квадратов в одном месте.

Можно предположить, что Board должен просто попросить у каждого Square значение его состояния. Хотя такой подход и возможен в React, мы его не одобряем, потому что код становится сложным для понимания, восприимчивым к ошибкам и трудным для рефакторинга. Вместо этого лучше всего хранить состояние игры в родительском компоненте Board , а не в каждом Square . Компонент Board может указать каждому Square , что отображать, передавая свойство, точно так же, как мы это делали, когда передавали число в каждый Square .

Чтобы собрать данные из нескольких дочерних элементов или обеспечить взаимодействие двумя дочерними компонентами, вам нужно объявить общее состояние в их родительском компоненте. Родительский компонент может передать состояние обратно дочерним компонентам, используя свойства props ; это синхронизирует дочерние компоненты между собой и с родительским компонентом.

Поднятие состояния в родительский компонент является обычным явлением при рефакторинге компонентов React — давайте воспользуемся этой возможностью. Мы добавим конструктор в Board и установим его начальное состояние так, чтобы оно содержало массив с 9 нулями. Эти 9 нулей соответствуют 9 квадратам:

Когда мы позже заполним Board , игровая доска будет выглядеть примерно так:

В настоящее время метод renderSquare в Board выглядит следующим образом:

В начале мы передали свойство value вниз по иерархии компоненту Square из Board , чтобы показывать числа от 0 до 8 в каждом Square . В другом предыдущем шаге мы заменили числа знаком « X », определяемым собственным состоянием Square. Вот почему Square в настоящее время игнорирует свойство value , переданное ему компонентом Board .

Теперь мы снова будем использовать механизм передачи свойств. Мы изменим Board , чтобы проинструктировать каждый отдельный Square о его текущем значении (« X », « O » или null ). У нас уже определен массив squares в конструкторе Board . Давайте изменим метод renderSquare в Board , чтобы читать значения из массива:

Каждый Square теперь получит свойство value , которое будет либо « X »/« O », либо null для пустых квадратов.

Далее нам нужно изменить то, что происходит при нажатии на квадрат. Компонент Board теперь знает, какие квадраты заполнены. Нам нужно создать для Square способ обновить состояние Board . Поскольку состояние считается приватным по отношению к компоненту, который его определяет, мы не можем обновлять состояние Board напрямую из Square .

Чтобы сохранить состояние Board приватным, мы передадим функцию из компонента Board компоненту Square . Эта функция будет вызываться при нажатии на квадрат. Мы изменим метод renderSquare в Board на:

Мы разбиваем возвращаемый элемент на несколько строк для удобства чтения и добавляем скобки, чтобы JavaScript не вставлял точку с запятой после return ломая наш код.

Теперь мы передаем потомкам два свойства из Board в Square : value и onClick . Свойство onClick — это функция, которую Square может вызывать при нажатии. Внесем следующие изменения в Square :

Заменим this.state.value на this.props.value в методе render компонента Square

Заменим this.setState() на this.props.onClick() в методе render компонента Square

Удалим конструктор из Square , потому что он больше не отслеживает состояние игры

После этих изменений компонент Square выглядит следующим образом:

При нажатии на квадрат вызывается функция onClick() , предоставляемая Board . Вот как это достигается:

Свойство onClick() в нативном DOM-компоненте указывает React установить слушатель событий щелчка.

При нажатии на кнопку React вызывает обработчик события onClick() , определенный в методе render() компонента Square .

Этот обработчик событий вызывает this.props.onClick() . Свойство onClick компонента Square было определено компонентом Board .

Так как Board передал onClick = <() =>this.handleClick(i)> в Square , Square при нажатии вызывает this.handleClick(i) .


Мы пока не определили метод handleClick() , поэтому наш код выдает крэш.

Атрибут onClick DOM-элемента имеет особое значение для React, поскольку он является нативным компонентом. Для пользовательских компонентов, таких как Square , наименование зависит от вас. Мы могли бы как угодно назвать метод onClick компонента Square или метод handleClick компонента Board . Однако в React принято использовать имена on[Event] для свойств, которые представляют события, и handle[Event] для методов, которые обрабатывают события.

Когда мы попытаемся кликнуть по квадрату, мы должны получить ошибку, потому что мы еще не определили handleClick . Теперь мы добавим handleClick в класс Board:

После этих изменений мы снова можем нажимать на квадраты, чтобы заполнить их. Однако теперь состояние хранится в компоненте Board вместо отдельных компонентов Square . При изменении состояния Board компоненты Square автоматически перерисовываются. Хранение состояния всех квадратов в компоненте Board в будущем позволит определить победителя.

Поскольку компоненты Square больше не поддерживают состояние, они получают значения от компонента Board и информируют компонент Board при клике по ним. В терминах React-компоненты Square теперь являются контролируемыми компонентами. Board их полностью контролирует.

Обратите внимание, что в handleClick мы вызываем .slice() , чтобы создать копию массива квадратов для его изменения вместо изменения существующего массива. Мы объясним, почему мы создаем копию массива квадратов в следующей главе.

Почему важна неизменяемость

В предыдущем примере кода мы предложили использовать оператор .slice() , чтобы создать копию массива квадратов для изменения вместо изменения существующего массива. Теперь мы обсудим неизменяемость и то, почему важно её изучить.

Как правило, существует два подхода к изменению данных. Первый подход заключается в мутировании данных путем прямого изменения значений. Второй подход заключается в замене данных новой копией, которая имеет желаемые изменения.

Изменение данных с помощью мутации

Изменение данных без мутации

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

Сложные функции становятся простыми

Неизменяемость делает сложные функции намного проще в реализации. Позже в этом учебнике мы реализуем функцию «путешествие во времени», которая позволяет нам просматривать историю игры в крестики-нолики и «перепрыгивать» к предыдущим ходам. Такая функциональность не является специфичной для игр — способность отменять и повторять определенные действия является распространенным требованием в приложениях. Избежание прямой мутации данных позволяет нам сохранить предыдущие версии истории игры нетронутыми и использовать их позже.

Отслеживание изменений

Обнаружить изменения в мутируемых (изменяемых) объектах сложно, потому что они изменяются напрямую. Такое обнаружение требует, чтобы изменяемый объект сравнивался с предыдущими копиями самого себя и всего дерева объектов перемещения.

Обнаружение изменений в неизменяемых объектах значительно проще. Если неизменяемый объект, на который ссылаются, отличается от предыдущего, то объект изменился.

Определение момента, когда необходима перерисовка в React

Основным преимуществом неизменяемости является то, что она помогает создавать чистые компоненты в React. Неизменяемые данные могут легко определить, были ли внесены изменения, что в свою очередь помогает определить, когда компонент требует повторной отрисовки.

Вы можете узнать больше о shouldComponentUpdate() и о том, как создавать чистые компоненты, прочитав раздел «Оптимизация производительности».

Компоненты-функции

Теперь мы изменим Square на компонент-функцию.

В React компоненты-функции являются более простым способом написания компонентов, которые содержат только метод отрисовки и не имеют своего собственного состояния. Вместо определения класса, который расширяет React.Component , мы можем написать функцию, которая принимает свойства props в качестве входных данных и возвращает то, что должно быть отображено. Компоненты-функции пишутся менее утомительно, чем классы, и многие компоненты могут быть выражены именно таким образом.

Заменим класс Square такой функцией:

Мы изменили this.props на props в обоих местах, где он встречается.

Когда мы выразили Square как компонент-функцию, мы также изменили onClick= <() =>this.props.onClick()> на более короткий onClick= (обратите внимание на отсутствие скобок с обеих сторон). В классе мы использовали стрелочную функцию для доступа к правильному значению this , но в компоненте функции нам не нужно об этом беспокоиться.

По очереди

Теперь нам нужно исправить очевидный дефект в нашей игре в крестики-нолики: буквы «O» не могут быть отмечены на доске.

Мы установим первый ход в «X» по умолчанию. Мы можем установить это значение по умолчанию, изменив начальное состояние в нашем конструкторе Board :

Каждый раз, когда игрок делает ход, xIsNext (логическое значение) будет инвертирован, чтобы определить, какой игрок пойдет дальше, и состояние игры будет сохранено. Мы обновим функцию handleClick в Board , чтобы инвертировать значение xIsNext :

С этим изменением «Х» и «О» могут сменяться. Давайте также изменим текст переменной status в методе render компонента Board , чтобы он отображал, какой игрок должен ходить следующим:

После применения этих изменений у вас должен получиться такой компонент Board:

Объявление победителя

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

Мы будем вызывать calculateWinner(squares) в методе render компонента Board , чтобы проверить, выиграл ли игрок. Если игрок выиграл, мы можем отобразить текст, такой как «Победитель: X» или «Победитель: O». Заменим объявление переменной status в методе render компонента Board следующим кодом:

Теперь мы можем изменить функцию handleClick в Board , чтобы выполнять return раньше, игнорируя клик, если кто-то выиграл игру или Square уже заполнен:

Поздравляем! Теперь у вас есть рабочая игра в крестики-нолики. Также вы только что изучили основы React, являясь, возможно, настоящим победителем.

Добавление путешествия во времени

В качестве последнего упражнения, давайте сделаем возможным «вернуться назад во времени» к предыдущим ходам в игре.

Хранение истории ходов

Если бы мы мутировали массив squares , реализация путешествия во времени была бы очень сложной.

Однако мы использовали slice() для создания новой копии массива squares после каждого перемещения и рассматривали его как неизменяемый. Теперь это позволит нам сохранять каждую прошлую версию массива squares и перемещаться между ходами, которые уже произошли.

Мы будем хранить прошлые массивы squares в другом массиве, называемом history . Массив history представляет все состояния Board , от первого до последнего хода, и имеет следующую форму:

Теперь нам нужно решить, какой компонент должен владеть состоянием history .

Очередное поднятие состояния

Мы хотим, чтобы компонент Game верхнего уровня отображал список прошлых ходов. Для этого ему понадобится доступ к history , поэтому мы поместим состояние history в компонент Game верхнего уровня.

Помещение состояния history в компонент Game позволяет нам удалить состояние squares из его дочернего компонента Board . Подобно тому, как мы «подняли состояние» из компонента Square в компонент Board , теперь мы поднимаем его из Board в компонент Game верхнего уровня. Это дает компоненту Game полный контроль над данными Board и позволяет ему инструктировать Board отрисовывать предыдущие ходы из history .

Во-первых, мы установим начальное состояние для компонента Game в его конструкторе:

Далее у нас будет компонент Board , получающий свойства squares и onClick из компонента Game . Так как теперь у нас есть единый обработчик кликов в Board для всех Square , нам нужно будет передавать местоположение каждого Square в обработчик onClick , чтобы указать, на какой квадрат кликнули. Вот необходимые шаги для преобразования компонента Board :

Удалить конструктор в Board.

Заменить this.state.squares[i] на this.props.squares[i] в методе renderSquare компонента Board .

Заменить this.handleClick(i) на this.props.onClick(i) в методе renderSquare компонента Board .

Компонент Board теперь выглядит так:

Обновим функцию render компонента Game , чтобы использовать самую последнюю запись в истории для определения и отображения статуса игры:

Поскольку компонент Game теперь отображает статус игры, мы можем удалить соответствующий код из метода render компонента Board . После рефакторинга функция render в Board выглядит так:

Наконец, нам нужно переместить метод handleClick из компонента Board в компонент Game . Нам также нужно изменить handleClick , поскольку состояние компонента Game структурировано по-другому. В методе handleClick компонента Game мы объединяем новые записи истории в history .


В отличие от метода push() массива, с которым вы, возможно, более знакомы, метод concat() не изменяет исходный массив, поэтому мы предпочитаем его.

На данный момент компонент Board нуждается только в методах renderSquare и render . Состояние игры и метод handleClick должны находиться в компоненте Game .

Показ предыдущих ходов

Поскольку мы записываем историю игры в крестики-нолики, теперь мы можем отобразить ее игроку в виде списка прошлых ходов.

Ранее мы узнали, что элементы React являются первоклассными объектами JavaScript; мы можем передавать их в наших приложениях. Чтобы отрисовывать несколько элементов в React, мы можем использовать массив React элементов.

В JavaScript у массивов есть метод map() , который обычно используется для отображения данных на другие данные, например:

Используя метод map , мы можем сопоставить нашу историю ходов с элементами React, представляющими кнопки на экране, и отобразить список кнопок, чтобы «перейти» к прошлым ходам.

Давайте сопоставим историю в методе render компонента Game :

Для каждого хода в истории игры в крестики-нолики мы создаем элемент списка
, который содержит кнопку . Эта кнопка имеет обработчик onClick , который вызывает метод this.jumpTo() . Мы еще не реализовали метод jumpTo() . Пока что мы должны увидеть список ходов, которые произошли в игре, и предупреждение в консоли инструментов разработчика, которое гласит:

Each child in an array or iterator should have a unique “key” prop. Check the render method of “Game”.

Каждый дочерний элемент в массиве или итераторе должен иметь уникальное свойство » key «. Проверьте метод render компонента Game .

Давайте обсудим, что означает приведенное выше предупреждение.

Выбор ключа

Когда мы отображаем список, React хранит некоторую информацию о каждом отображаемом элементе списка. Когда мы обновляем список, React должен определить, что изменилось. Мы могли бы добавлять, удалять, переупорядочивать или обновлять элементы списка.

Представьте себе переход от

В дополнение к обновленным счетчикам, человек, читающий это, вероятно, сказал бы, что мы поменяли местами Петю и Васю и вставили между ними Лёню. Однако React — это компьютерная программа, которая не знает наших намерений. Поскольку это так, нам необходимо указать свойство key для каждого элемента списка, чтобы отличать его соседних элементов в этом списке. Один из вариантов — использовать строки vasia , petia , lyonia . Если бы мы отображали данные из базы данных, в качестве ключей могли бы использоваться идентификаторы (поле id) базы данных для Васи, Пети и Лёни.

При повторной отрисовке списка React берет ключ каждого элемента списка и ищет соответствующие элементы в предыдущем списке. Если в текущем списке есть ключ, которого раньше не было, React создает компонент. Если в текущем списке отсутствует ключ, который существовал в предыдущем списке, React уничтожает предыдущий компонент. Если два ключа совпадают, соответствующий компонент перемещается. Ключи сообщают React об идентичности каждого компонента, что позволяет React поддерживать состояние между повторными отрисовками. Если ключ компонента изменится, он будет уничтожен и воссоздан с новым состоянием.

Ключ — это специальное и зарезервированное свойство в React (наряду с ref , более продвинутой функцией). Когда элемент создан, React извлекает свойство key и сохраняет его непосредственно в возвращаемом элементе. Даже если key может выглядеть так, как будто он принадлежит props , на него нельзя ссылаться, используя this.props.key . React автоматически использует key , чтобы решить, какие компоненты обновлять. Компонент не может узнать о своем ключе key .

Настоятельно рекомендуется назначать правильные ключи key при создании динамических списков. Если у вас нет подходящего ключа key , вы можете подумать о реструктуризации ваших данных.

Если ключ не указан, React выдаст предупреждение и по умолчанию будет использовать индекс массива в качестве ключа. Использование индекса массива в качестве ключа вызывает проблемы при попытке изменить порядок или при вставке/удалении элементов списка. Явная передача key= отключает предупреждение, но имеет те же проблемы, что и индексы массивов, и в большинстве случаев не рекомендуется.

Ключи не должны быть глобально уникальными; они должны быть уникальными только между компонентами и их соседями. То есть уникальными только в пределах данного списка. В другом, к примеру соседнем списке, значения ключей могут совпадать со значениями текущего списка, но это никак не влияет на его работу, так как эти два подмножества ключей рассматриваются React полностью независимо, то есть они друг о друге не знают.

Реализация путешествия во времени

В истории игры в крестики-нолики каждый предыдущий ход имеет свой уникальный идентификатор — это порядковый номер хода. Ходы никогда не переупорядочиваются, не удаляются и не вставляются в середину, поэтому здесь безопасно использовать индекс хода в качестве ключа.

В методе render компонента Game мы можем добавить ключ как
, и предупреждение React о ключах должно исчезнуть:

Нажатие любую из кнопок элемента списка приводит к ошибке, потому что метод jumpTo не определен. Прежде чем мы перейдем к реализации jumpTo , добавим stepNumber в состояние компонента Game , чтобы указать, какой шаг мы сейчас просматриваем.

Мастер Йода рекомендует:  Как айтишнику искать и найти первую работу — отвечают эксперты

Сначала добавим stepNumber: 0 в начальное состояние в конструкторе Game :

Далее мы определим метод jumpTo в Game , чтобы обновлять stepNumber . Мы также устанавливаем xIsNext в true , если число, на которое мы меняем stepNumber , является четным:

Теперь мы внесем несколько изменений в метод handleClick комопнента Game , который срабатывает при нажатии на квадрат.

Добавленное нами состояние stepNumber отражает текущий ход, отображаемый для пользователя. После того, как мы сделаем новый шаг, нам нужно обновить stepNumber , добавив stepNumber: history.length в качестве аргумента this.setState . Это гарантирует, что мы не застрянем, показывая тот же самый ход после того, как был сделан новый.

Мы также заменим чтение this.state.history на this.state.history.slice(0, this.state.stepNumber + 1) . Это гарантирует, что если мы «вернемся назад во времени», а затем сделаем новый шаг с этой точки, мы затрем всю «будущую» историю, которая теперь стала бы неверной.

Наконец, мы изменим метод render компонента Game , на данный момент всегда отрисовывающий последний ход, чтобы он отрисовывал текущий выбранный ход в соответствии со stepNumber :

Если мы нажмем на какой-либо шаг в истории, игровое поле должно немедленно обновиться, чтобы показать, как оно выглядело после того, как этот шаг произошел.

Подведение итогов

Поздравляем! Вы создали игру в крестики-нолики, которая:

позволяет вам играть в крестики-нолики,

показывает, когда игрок выиграл,

хранит историю игры,

позволяет игрокам просматривать как историю игры, так и предыдущие версии игрового поля.

Отличная работа! Мы надеемся, что теперь вы почувствовали, что хорошо понимаете, как работает React.

Проверьте окончательный результат здесь: Окончательный результат

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

Отображение местоположения для каждого хода в формате (столбец, строка) в списке истории ходов.

Выделите текущий выбранный элемент в списке ходов.

Перепишите компонент Board , чтобы использовать два цикла для создания квадратов вместо их жесткого кодирования.

Добавьте кнопку-переключатель, которая позволяет сортировать ходы в порядке возрастания или убывания.

Когда кто-то выигрывает, выделите три квадрата, которые привели к победе.

Когда никто не выигрывает, выведите сообщение о ничье.

Критика работы с React Native: наш опыт

При выборе языка React Native ожидается, что разработка одного приложения под две платформы займёт в два раза меньше времени, чем разработка двух приложений. Но по итогу оказывается, что разработка занимает столько же (если не больше) из-за сложностей, скрытых под внешним блеском и маркетингом.

В свете последних тенденций на рынке разработки ПО Android разработчик BytePace, Виктор Кинько, расскажет о некоторых подобных сложностях, с которыми ему пришлось столкнуться за последние несколько месяцев работы с React Native.

React Native адаптирует javascript под разработку для мобильных устройств. Это достигается тем, что для сборки проектов он использует несколько сборщиков — Metro Bundler, который интерпретирует JS-код и представляет ресурсы и сборщик целевой системы. В моем случае это был gradle для android. В теории приложение react-native должно запускаться довольно просто. Команда react-native run-android включает metro bundler и выполняет сборку приложения для всех подключенных android-устройств и эмуляторов.

В реальности оказалось, что даже на этом этапе есть сложности. На нашем проекте постоянно возникала ошибка «Unable to download JS bundle», которая означала, что bundler не может транслировать код в нативный. Как позже выяснилось, из-за того, что он не запустился. StackOverflow подтвердил догадки и подсказал, что стоит запускать bundler отдельным потоком с помощью команды react-native start. Это позволяет перезапускать bundler только если поменялся package.json, потому процедура не сильно замедляет разработку.

Package.json — это файл, содержащий набор внешних модулей для приложения. На npmjs.com находится большое количество различных библиотек для react-native, расширяющих функционал и упрощающих разработку. Многие библиотеки (например, firebase) используют нативные функции, а потому должны быть связаны напрямую с нативным кодом. Для этого используется команда react-native link , которая должна настраивать эти связи с нативным кодом.


Из-за того, что все библиотеки пишутся в разное время, они используют разные версии SDK и требуют разного подхода. Иногда бывает так, что библиотеки несовместимы друг с другом, или последняя версия библиотеки оказывается экспериментальной, и сами разработчики советуют понизить версию до предпоследней. Довольно часто link не настраивает все требуемые зависимости. Так, для вышеупомянутого firebase требуется добавить множество дополнительных библиотек в нативном коде, подключить различные внешние репозитории, модифицировать mainApplication.java (и это только для android!). Для firebase есть достаточно понятная инструкция по выполнению этих действий, но для других библиотек она присутствует не всегда.

После того, как связи с нативным кодом настроены, можно собирать проект в надежде, что подключенная библиотека заработает. При сборке стоит помнить, что если вы получаете ошибку, то стоит удостовериться, что она возникла именно из-за ваших действий, а не из-за ошибки сборщика. Для полной уверенности стоит выполнить следующую последовательность действий:

• rmdir node_modules /s /q && npm cache clean-force && npm i

Данная команда удалит папку node_modules, а затем загрузит её заново. Это одна из самых долгих задач, потому стоит использовать её крайне редко. На некоторых проектах node_modules может занимать до нескольких гигабайт на жестком диске, а потому переустановка займёт время.

• rmdir android/app/build /s /q

В ходе разработки было замечено, что часто неудачный билд — следствие того, что сборщик не может создать (или удалить) папку из директории debug. Данное действие решает проблему того, что react не может самостоятельно удалить папку. Но в то же время генерация файлов для этой папки с нуля опять же займёт дополнительное время.

Запустить Metro Bundler. Эта вкладка должна оставаться открытой на протяжении всего процесса отладки. Если случилась ошибка, то лог ошибки может появиться здесь. Скорее всего при ошибке этот процесс завершится, и его снова нужно будет перезапустить.

Установить приложение на подключенное устройство или эмулятор. Большинство ошибок сборки случаются именно здесь, и часть из них понятна, но часть довольно иррациональна и «лечится» перезапуском всего процесса.

Представим процесс сборки последовательностью команд для одного проекта (уже имеющего realm, redux, react-navigation, ещё около десяти библиотек) после подключения firebase.

Стоит ли говорить, что это занимает действительно много времени? И это не единоразовый процесс: к описываемому моменту эта процедура требовалась почти после каждого изменения в коде программы. С каждой новой библиотекой проект становится всё менее стабильным, и данный процесс может меняться, чаще всего в худшую сторону. Отладка приложения — это одна из важнейших функций для разработчика, а в данном случае её скорость довольно сильно уменьшается.

Кстати об отладке. Отладчик React Native имеет проблемы не только с запуском. Исправление ошибок, найденных вследствие теста, тоже довольно болезненный процесс. В react-native JS-код транслируется в Native-код, но в процессе трансляции обфусцируется. Так что если не хотите видеть ошибки типа «null pointer exception in zzz.yyy()», то нужно пользоваться встроенным отладчиком, не получится просто читать exception’ы в logcat. При ошибке отладчик показывает красный “экран смерти” с её описанием, более-менее подталкивающим в сторону пути исправления. Но и с этой частью есть проблемы.

Хорошо, когда ошибка выглядит так:

Здесь действительно понятно, что происходит — вместо ожидаемого объекта массива в переменной this.state.noteArray.map находится undefined, из-за чего возникает пресловутая TypeError. Исправить её можно переходом на app.js:14 и проверкой значения в данной переменной перед использованием.

Хуже, когда ошибка выглядит так:

Изображения взяты из интернета, но я видел их и «вживую». И несмотря на то, что они показываются в runtime, эта ошибка не связана с тем, что что-то было сделано неверно именно в вашем коде. Это может быть следствием того, что вы неверно установили библиотеку, или если в ваших импортах есть несовместимые зависимости, или что-то пошло не так в native-коде, а ошибку пытается отловить React. Каждая ошибка индивидуальна и решается крайне по-разному. Хорошо, что существует StackOverflow и хоть какой-то режим отладки.

Еще хуже, когда ошибка не воспроизводится в debug. С данной ситуацией я столкнулся при попытке собрать приложение с новой версией React с поддержкой x64-архитектур для Android. При установке приложения с дебаггером всё работает отлично. Но как только я делаю сборку тестеру на телефон, всё прекращает работать и ломается как только доходит до взаимодействия с базой данных. Чтобы отладить неотлаживаемое, на скорую руку используем консольные сообщения, в роли которых в данном случае выступал компонент react toastAndroid. Этот компонент выводит на экран короткий текст по достижению определенной строчки кода. Методично, желательно деля код пополам, локализуем функцию, в которой происходит ошибка, и выясняем, что метод Object.assign(<>, item) не работает в новой версии React. Повезло, что можно было заменить эту функцию на более короткую <. item>при сохранении функционала приложения, но поиск этой ошибки обошелся в примерно десяток часов работы.

После было проведено небольшое исследование в поисках причин. Как обнаружилось, для интерпретации JS-кода в debug и production версиях React Native использует разные Javascript-движки: для отладки Chrome JS engine, а в работе JavaScriptCore. Да, React Native не переводит JavaScript в нативный код, а интерпретирует по ходу выполнения. При этом отладочный движок работает куда стабильнее, а потому баги всё чаще прокрадываются в production. К примеру, в этой статье показано, как форматирование даты работает в разных условиях. Возвращаясь к ошибке: так вышло, что после обновления версии React Native веб-движок production-версии потерял поддержку Object.assign(). А отладочный движок остался тот же.

Пожалуй, худший вариант — это случай, когда приложение ломается в случайных местах, только в production-версии и без каких-либо логов со стороны React Native. Пример: после установки релизной версии приложения на телефон оно «работает какое-то время», а потом «выключается без ошибки или предупреждения в случайный момент». Причём ошибка воспроизводится не на всех устройствах. В конце концов, методом проб и ошибок (и обнаружением того, что вышеупомянутый Firebase Crashlytics не присылает соответствующих ошибок) удалось выловить логи падения, которые выглядели так:

Этот текст даже не относится к нашему приложению, он даже не был отмечен красным. Но после того, как я его получил и отправился на форумы, я обнаружил, что новая версия React Native сломана. И предыдущая была сломана. На официальном Issue Tracker ошибка «Android crashes: signal 11 (SIGSEGV)» существовала уже два месяца, и к моей удаче за два дня до того, как я обратился туда(!), было предложено экспериментальное решение, которое исправило ошибку.

Иронично, что некоторые разработчики, которым приходилось сталкиваться с Android Studio, были в недоумении по поводу того, что в IDE есть такие опции как build/clean project или file/invalidate caches. Это требуется для того, чтобы избавиться от аномального поведения gradle, от ложных сообщений об ошибках и предупреждениях, от ошибок синхронизации. Разработчики спрашивали: «почему мы должны делать работу за нашу IDE, в таких ситуациях эти команды должны выполняться автоматически». И их можно понять, но в то же время современные IDE и так делают всю сложную работу за кадром. А эти разработчики попросту не работали с React Native.

Всё рассказанное — это единичные случаи, случившиеся за последние несколько недель. Здесь я не описываю сложности запуска приложений с Expo, с настройкой стиля кода в babel/eslint, не ругаю Javascript за излишнюю гибкость, не рассказываю как на одном из проектов почти полностью пропала возможность отладки из-за связки redux/realm. Учитывая описанные сложности поддержки и разработки и тот факт, что для двух систем это всё умножается на два, стоит задуматься, действительно ли React Native выгоден для разработки? После того как мы завершили наш третий проект на этом языке, мы решили, что нет. Как вы считаете?

Материал опубликован пользователем.
Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Все ваши проблемы с рн из за того что вы не удосужились почитать официальную доку, либо читали невнимательно, в частности то что в дебаге код запускается в v8, а не в jsc.

Меня на реакт подбил знакомый, работающий с React JS. До этого работал на на нативе android , iOs.
Достаточно легко было нарисовать простой список элементов, получаемых с сервера. Но когда дело пошло дальше: новостная лента, вебвью, перехват и обработка запросов, работа с БД — началась адская боль и страдания. Наверное надо быть js ником в третьем поколении, чтобы это выдержать. Война с версиями библиотек. Под айос еще как-то. pod install и все. Но с андроидом с градлом. Не в градле дело, а в вечных конфликтах версий. Да, запустилось на андроиде и не идет на айос. И наоборот. Куча кастомных приблуд. Куча ограничений. Не советую никому, кто будет писать что-то функциональное, мало-мальски сложнее презентационной странички. Тем более если вы отлично дружите с нативной разработкой на типизированных языках. После реакта пропало желание смотреть в сторону Flutter и прочих кросплатформенных приблуд. Пока что углубляюсь в котлин и свифт.

Отдельно отметил бы вёрстку в RN — это только псевдо верстка под браузеры. На самом деле очень много нюансов есть и часто приходится юзать платформозависимые стили.

А даёт ли это какой-то результат в скорости разработки или качестве.

Как написавший 3 аппы в 2012-2014 годах, на более качественной с точки зрения перфоманса(хороший мультитрединг), кроссплатформе Adobe AIR, я ушел все равно в чистый нейтив. Сегодня просто божественные инструменты для того, чтобы силами одного разраба сделать Swift и Kotlin нейтив: кодогенерации в оба языка, схожие UI-либы, даже местами можно копипастить код как есть. Ни один сегодня опытный разраб не вляпается в кроссплатформу.
Правда есть одна работающая бизнес-модель кроссплатформы, это Unity для игр, но там надо много платить — только на таких финпотоках можно поддерживать кроссплатформенный движок в актуальном состоянии

Вы знаете, я в итоге пришел к тому, что для MVP лучше использовать не RN, а RN + webview. Я не представляю, как делать на RN сложные графические вещи, анимации и пр. Исходя из этого делаю предположение, что RN — это больше про аналог мобильных версий сайтов завёрнутых в приложение. Так вот вёрстку и бизнес логику можно заменить вебвью, а от RN использовать только нужное: пуши, геолокацию и другие специфические штуки. И вот этот подход очень сильно ускоряет разработку,т.к. в итоге нужно соблюсти только кроссбраузерность(safari + chrome).

PS
По факту разрабатывали одно приложение на RN, потом переделали на RN + webview. По качеству стало лучше — перестало крашиться, анимации стали быстрее. По скорости разработки несравнимый буст. И релизишся быстро и разрабатываешь намного быстрее.

PSS
Надеюсь webview не запретят.

Может быть вам больше подойдёт Cordova? Мы на Cordova даже виртуальную реальность реализовали.

Можно попробовать конечно, но тут все зависит от задачи. На мой взгляд, если можно обойтись вебвью, то лучше ее и использовать. А на счёт чем ее обернуть — лучше наверное нативные языки, это не долго и не дорого.

Интересно было почитать о вашем опыте. Часто чешутся руки его изучить, особенно после комментариев под моей очередной статьей об Ionic Framework, что React Native круче.

Расскажите как сложно верстать кастомный дизайн приложения в React Native? Само собой в сравнении с нативом.

Здравствуйте, спасибо за отзыв!
С Ionic совсем не знаком, потому не знаю насколько React лучше или хуже, но опыт несомненно интересный.

Если говорить о дизайне, то React Native в этом плане очень похож на верстку для веба с использованием css и Flexbox. Стоит заметить, что чаще всего лейауты связаны с функционалом, то есть у каждого компонента есть список входящих атрибутов, которые он поддерживает, что заставляет разработчика обеспечивать модульность при создании своих компонентов. Довольно оригинально и в то же время странно ощущается система обновлений элементов, когда к ним применяются новые атрибуты. С этим пришлось свыкнуться, поначалу разбирались и с тормозами, и с отсутствием перерисовки элементов по этой причине.

С простыми элементами проблем не возникало совершенно, разница незначительная, где-то, если привыкнуть, React получится даже быстрее в вёрстке. Несколько неудобным показалось делать лейауты с наслаивающимися элементами. Но самые большие сложности возникали при вёрстке платформенно-специфических компонентов и компонентов со встроенной сложной логикой.

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

В своё время мы тоже прошли этот путь, от Cordova до наивной разработки. В начале у всех разработчиков, пришедших из веба, есть боязнь использования каких‐то Kotlin и Swift, но все не так страшно на практике, и даже затягивает )) Многие англоязычные блогеры замечают, React Native хорош . для создания прототипа. Большие проекты очень тяжело поддерживать в RN. Далее будут всплывать проблемы с переходом от старой версии RN к более новой.

Ещё хочется добавить. Жирный минус в RN, по крайней мере для iOS, отсутствие поддержки контроллеров. Мы работали с дополненной реальностью, и был готовый контроллер из ARKit. Модуль для RN в этом случае поступает просто, создаёт статический класс ARView, который живёт всегда. Приходится как-то останавливать его. короче, убийца Айфона (его батарейки )))

RN вроде и не предназначен для подобного рода приложений( игры/дополненная реальность )
Для них логичней какой-нибудь Unity или Unreal попробовать

Довольно.. забавное описание.
Ощущение, что процесс разработки происходил на линукс с его вечным цирком в плане прав доступа.
Бандлер обычно запускают отдельной командой, т.к это удобней( и можно почистить его кеш в случае странностей, т.е npm start — —rest-cache )
Часть ошибок( из показанного на скринах ) — ошибки связанные именно с JS. К примеру, вместо массива прилетел с бука объект или вообще null. Как ни странно, метода map у него не будет и попытка выполнения его вызовет ошибку.
Еще часть — когда отладка происходит на подключенном к ПК телефоне( обычно помогает adb reverse )
Далее, по крашам. Если приложение просто вылетает( тихо выключается ) — это сбой в нативной части. Если вместо приложения — вдруг красный(отладка) / белый(релиз) экран — сбой в JS части.

Package.json — файл, относящийся к npm, т.е пакетному менеджеру.
Штука позволяет довольно удобно настраивать версии пакетов.
npm — это не чисто RN-приблуда. Соотв., на npmjs полным-полно модулей, к RN не относящихся( там и для React.JS модули есть и для Node.JS и для многого другого )

Да, подключение модулей( особенно, файербейса и ФБ/Твиттера/Гугла — это обычно самая боль ) не всегда происходит запросто. Однако в разработке, подключение модулей происходит нечасто. Это не то действие, которое выполняется ежедневно и по 10 раз в день. Если вы подключили файербейс к андроиду, второй раз это делать не придется.
Если это сколь-нибудь большое приложение, то подавляющая часть времени — это работа с версткой( и эта часть реально сильно сокращается в сравнении с независимой разработкой для 2 платформ ).

Основная часть ошибок, связанных с работой при подключенном отладчике и не_работой — без отладчика, обычно относится к работе с сетью.
При подключенном отладчике, JS код исполняется на полноценном подобии браузерного движка( т.е даже с некоторыми соотв. глобальными объектами и всякими плюшками при запросах ), без него — соотв., без перечисленного.

Основани часть ошибок, связанных при установке-подключении модулей, возникает из-за непонимания очевидных вещей:
Если был подключен нативный модуль( т.е был выполнен react-native link ), очевидно, что проект нужно полностью пересобрать. Желательно, почистить от старой сборки. Особенно проблемами с этим грешит android и gradle( этот «гений» создает столько мусора, что сам порой в нем разобраться не может ).
Если был подключен просто_JS модуль( т.е просто установлен через пакетный менеджер, без линковки ), полная переборка не требуется достаточно перезагрузить приложение( всм, Reload JS ).
В обоих вариантах лучше перезапустить бандлер( прибить и выполнить npm start — —reset-cache ).

5 лучших курсов по React Native для разработчиков мобильных приложений

Если вы — веб-разработчик, который хочет создавать мобильные приложения, но не хочет тратить время на изучение Java/Kotlin (для Android) или Objective C/Swift (для iOS), то вам отлично подойдет React Native.

React Native является ответвлением React — популярного JavaScript-фреймворка для разработки веб-приложений. Он позволяет создавать нативные Android и iOS приложения в JavaScript.

В отличие от Ionic и Cordova, поддерживающих принцип write once run everywhere, но не позволяющих создавать нативные приложения, React Native может преобразовывать ваш код в нативный, особенно если речь идет о графическом интерфейсе.

То есть, вместо запуска программы в браузере или WebView (для Ionic и Cordova) вы можете просто написать нативное приложение для Android и iOS в JavaScript.

Это огромный плюс для JavaScript-разработчиков, мечтающих создавать свои приложения.

Популярность React Native с Redux стремительно растет. Поэтому если вы ищите работу в сфере разработки мобильных приложений — подобные знания станут ценным пунктом в резюме.

React Native предоставляет отличное решение для разработки мобильных приложений за тот же отрезок времени, который требуется для создания приложения на iOS или Swift.

5 лучших курсов для изучения React Native


Если вы уже читали мои статьи, то знаете про мою трехступенчатую формулу для изучения новой технологии или фреймворка.

Она помогла мне освоить множество нового, в том числе Git, Spring и Hibernate. И чтобы прокачать свои технические навыки в 2020 году, я пользуюсь той же формулой для изучения Kotlin, Docker, и анализа данных.

Как правило, мое обучение начинается с качественного онлайн-курса, в котором разъясняются основы технологии и дается небольшой практический опыт по части настройки и создания простейших приложений.

Как только основы поняты, я иду дальше и берусь за книгу с подробным объяснением того же материала и добавлением нового.

Мастер Йода рекомендует:  Википедия создаёт свой собственный поисковый движок, чтобы конкурировать с Google

После прочтения книги и прохождения онлайн-курса, я приступаю к созданию настоящего приложения. Параллельно проверяю свои практические навыки и заполняю пробелы в знаниях.

Вот здесь-то и начинается основное обучение. Если мне нужно узнать что-то новое, то я снова и снова возвращаюсь к пройденному курсу или прочитанной книге.

Давайте начнем с подборки лучших курсов по изучению React Native и разработке нативных мобильных приложений на JavaScript.

1. The Complete React Native and Redux Course

Это один из лучших курсов по изучению React Native и Redux. Он поможет вам быстро освоить React Native и начать с ним работать, а также научит необходимым знаниям, которые потребуются для понимания и создания React-компонентов для мобильных устройств.

Курс начинается с объяснений основ React: JSX, props (свойства), состояния и обработка событий. Так что даже если вы совершенно не знакомы с фреймворком React — можете смело начинать с React Native. Курс не только поможет вам разобраться в основах React, но и даст определения терминам и концепциям Redux — еще одного популярного JavaScript фреймворка для создания интерфейсов.

Вы научитесь быстро создавать прототипы и развертывать приложения в Apple Store и Google Play.

Итого: перед вами один из наиболее полных курсов по быстрому изучению React Native и Redux.

2. React Native: Advanced Concepts

Еще один курс по React Native от того же автора — Стивена Грайдера, который позволит вам поднатореть в более сложных темах: анимации, картах, уведомлениях, навигации и т.д.

Курс научит вас теоретическим и практическим основам реализации сложных анимационных систем и загрузки приложений на новой платформе Expo. Кроме того, вы освоите пользовательскую навигацию в React-Navigation.

А еще научитесь аутентификации через Facebook OAuth, вовлечению пользователей автоматическими push-уведомлениями, увеличите поток аутентификации в приложении с одноразовыми паролями из Twilio и повысите надежность приложения с оффлайн сохранностью данных.

Итого: выбирайте оба курса этого автора и становитесь профи в React Native за 1–2 месяца.

3. React Native — The Practical Gu >Классный курс по React Native от Udemy. Мне действительно понравился способ подачи материала для веб-разработчиков. Автор курса рассказывает, как создавать качественные нативные приложения для мобильных с помощью тех же веб-технологий, которыми вы пользуетесь при написании отзывчивых веб-приложений.

Здесь вас научат создавать собственные приложения на React Native, размещать их в Google Play Store и Apple App Store, а также с головой погружаться в экосистему React Native.

Еще вы узнаете о теоретических аспектах React Native, его ключевых составляющих, а также научитесь созданию отзывчивых дизайнов, которые отлично работают на устройствах любых размеров. Вам покажут, как анимировать приложения на React Native, как устроена навигация, как пользоваться картами и камерой и т.д.!

Итого: это практический и современный курс для самостоятельного изучения React Native с интересной подачей материала.

4. Create Your First React Native App

Ударный курс по созданию собственного приложения на React Native за пару дней. Если вы считаете себя любознательным разработчиком, которому больше по душе действие, а не чтение книг, то этот курс создали специально для вас.

Его цель — предельно быстро поставить вас на ноги и научить работе с React Native, а также рассказать о ключевых аспектах разработки на React Native.

Курс не является всеобъемлющим источником знаний. Он, скорее, рассчитан для быстрого старта и создания прочной практической базы.

Итого: отличный курс для желающих поработать с React Native и разработчиков в поисках альтернатив Cordova и Ionic.

5. Build an app in less than 1 hour using React Native

Иногда, если я хочу поскорее познакомиться с какой-то технологией, то просто сажусь и начинаю писать в ней приложения, параллельно изучая нужную мне информацию.

Данный курс как раз и рассчитан на такую модель поведения и обещает научить вас принципам работы React Native в процессе создания прикольного приложения в стиле Tinder.

Здесь вы научитесь JSX — популярному языку разметки React, его сочетанию с HTML и JavaScript, а также разбивке крупных приложений на меньшие компонентные единицы с повторным использованием их в коде.

Вас познакомят с принципами работы свойств и состояний. И самое главное — вы поймете, что это, чем они занимаются, и зачем вообще нужны.

Итого: отличный стартовый курс для погружения в чудесный мир разработки мобильных и десктопных приложений.

Заключение

Это все, что я могу сказать о лучших курсах по React Native и разработке мобильных приложений для Android и iOS, используя JavaScript.

React Native — отличный фреймворк, который сокращает время обучения и написания продукта, а также позволяет быстро создавать и распространять приложения вашей мечты.

В отличие от Ionic и Cordova, здесь вы действительно сможете создавать нативное приложение с нативными компонентами графического интерфейса.

Итого: React Native — это самый быстрый способ создания нативных мобильных приложений на iOS и Android. Он заслужил доверие таких гигантов, как Facebook, Instagram, Uber, Airbnb и др. Если в 2020 году вы решили изучить нечто новое, то React Native, безусловно, станет отличным выбором.

Простое и понятное введение в React Native

React Native является относительно простым фреймворком для разработки кроссплатформенных приложений для iOS и Android на JavaScript, но во многих введениях по нему материал даётся сложным и запутанным образом. Перед началом работы нужно что-то устанавливать, настраивать, выяснять необходимость наличия компьютер Mac и прочее. Официальная документация написана неплохо, но введение в React Native можно сделать проще и понятнее.

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

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

Рассмотрим простой пример.

Для создания приложений в React Native используется расширенный JavaScript стандарта ES2015.

import React from ‘react’;

необходима для поддержки JSX. JSX — это синтаксис, позволяющий встраивать XML в JavaScript. Если строку импорта убрать, то блок кода

будет помечен как ошибочный.

происходит подключение к проекту модуля Component. Без этой строки при создании класса пришлось бы указать export React.Component.

Далее в коде создаётся класс HelloWorldApp, который является компонентом. Обратите внимание на то, что наш класс содержит в себе дочерние компоненты — View и Text. Это нужно понимать при работе с контекстом.

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

Здесь LotsOfGreetings является родительским пользовательским компонентом, а Greeting — дочерним пользовательским компонентом, который выводит приветствие в зависимости от параметра name.

— это структурный элемент, соответствующий компоненту Greeting.

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

Передача данных от родительского компонента дочернему производится посредством параметров props. Когда родитель перерисовывает дочерний компонент, то он отправляет ему параметры. Они доступны через this.props.

Фигурные скобки <> используются для вставки кода javascript в JSX структуру. Блочный javascript комментарий в JSX также необходимо заключить в фигурные скобки:

Если требуется расширить функциональность какого либо встроенного компонента, например, Button, то для этого мы не раздуваем его функциональность при помощи добавления атрибутов и свойств, как это происхоит в html и javascript, а создаём новый компонент, наследующийся от базового Component. Можно написать и extends Button, но это не приведёт к наследованию от кнопки и создания кастомной кнопки. Внешний вид компонента и его функциональность задаются явно, а не наследуются от родительского класса, как будет видно далее.

Вернёмся к исходному примеру.


import < Text, View >from ‘react-native’;

подключает к проекту классы компонентов, использующиеся в нём: Text — текстовая область и View — контейнерный компонент.

В каждом классе компонента необходимо определить метод render(), предназначенный для отрисовки его содержимого. Данный метод должен вернуть либо элемент React, либо null, если ничего отрисовывать не нужно.

В контексте React Native компоненты являются виджетами — объектами, имеющими видимое представление. Под отрисовкой (рендерингом) компонента понимается преобразование движком React Native разметки JSX в нативный вид путём вызова соответствующих методов API. В результате на экране устройства мы видим нативный интерфейс, а не его имитацию средствами web. При этом полученный интерфейс на iOS и Android будет отличаться. То есть, данный фреймворк не позволяет создать интерфейс, одинаково отображающийся и на iOS, и на Android.

Вся разметка компонента должна находиться в одном корневом контейнерном элементе. Следующий код вызовет ошибку:

Для устранения ошибки второй контейнерный элемент нужно вложить в первый.

Контейнерные компоненты могут содержать внутри себя другие компоненты. В контексте JSX контейнерный элементом является тот, который может отображать содержимое вложенных в него элементов. Например, элемент может содержать между открывающим и закрывающим тегом другие элементы, но это не делает его контейнером, так как данное содержимое не отображается.

Контейнерные и неконтейнерные элементы можно задать в форме самозакрывающегося тега:

Настройка компонентов происходит при помощи параметров двух видов — props (начальные неизменяемые параметры) и state (изменяемое состояние). Props часто называют свойствами, но это вносит путаницу так как под свойствами мы привыкли понимать изменяемую сущность. Тогда что это, атрибут, реквизит, свойство для чтения? Props следует понимать как параметры, которые можно передать компонентам в момент их создания и которые остаются фиксированными на протяженни всего жизненного цикла компонента. В примере

title является встроенным обязательным параметром, который нужно указать. Значение данного параметра можно получить, но его изменение не изменит надписи на кнопке:

this.props.title = «Новая кнопка»; // надпись на кнопке останется прежней — «Кнопка»

Более того, при перерисовке компонента (которое происходит при каждом изменении его состояния, о чём будет рассказано далее, изменении контекста или получении props от родителя) значения параметров сбрасываются в начальное состояние. Например, мы решили ввести свой параметр myParams:

Где-то в коде можно будет обратиться к нему и изменить его значение:

В другом месте кода можно будет его использовать, но при перерисовки компонента значение this.params.myParams останется равным «100».

Наряду со встроенными параметрами, которые изначально имеют встроенные компоненты, можно использовать пользовательские параметры при создании пользовательского компанента:

, где name — пользовательский параметр

или в конструкторе компонента:

constructor(props) <
super(props)
this.props.title = ‘myTitle’
>

Для доступа к параметру внутри JSX используются фигурные скобки:

Как изменить значение параметра (например, title), если оно является неизменяемым? Для этого используется состояние state. Данные, которые нужно изменить, необходимо преобразовать в состояния:

title — это параметр, а myTitle — это состояние, определённое в конструкторе так:

Имя состояния можно не заключать в кавычки. Если состояний несколько, то они перечисляются через запятую:

this.state = <
‘myTitle’:’Показать приветствие’,
‘name’:’Mate’,
‘age’:’25’
>

Преимущество данной записи состоит в том, что в случае организации цикла по свойствам компонента, в объект state попадут все указанные состояния. Если каждое состояние будет задано в отдельной строке при помощи this.state, то в выборку попадёт состояние, определённое последним.

Для получения состояни используется запись this.state.myTitle, а для изменения состояния используется метод setState:

Изменение состояния должно производиться только при помощи указанного метода. При любом изменении состояния компонента вызывается его метод render(). Каждое каждое лишнее действие в данном методе будет влиять на скорость отрисовки. При помощи специального метода можно откелючить перерисовку компонента.

В терминах React Native компонент может иметь много изначально заданных параметров (props), но находить в каждый момент времени в одном состоянии (state). При работе с компонентом мы меняем его состояние, а не параметры (или свойства). Предположим, в момент создания кнопка имеет какую-то надпись. Это значит то, что кнопка находится в состоянии отображения данной надписи. Если при помощи состояния надпись или её цвет были изменены, то это означает то, что теперь кнопка находится в другом состоянии с изменённой надписью или её цветом. Аналогичным образом можно описать состояние всех компонентов в проекте.

Атрибут ref

Вернёмся к кнопке:

Текущее значение параметра title в нашем случае можно получить при помощи состояния this.state.myTitle. Но как получить значение параметра title, если ему была присвоена строка? Для этого используется атрибут ref, принимающий функцию обратного вызова, параметром которого является ссылка на компонент, в котором она используется:

this.myButton = a> title=»Кнопка» onPress=/>

Теперь ссылка this.myButton будет указывать на компонент Button и можно будет получить значение его параметра title так:

или обратиться к методу компонента:

Рассмотрим более сложный пример c использованием стилей и событий.

Стили похожи на CSS, но фреймворк не использует CSS, хотя и заимствует многое из web разработки. Стиль представляет собой объект. При использовании встроенного стиля он заключается в двойные фигурные скобки, так как объекты в javascript заключаются в фигурные скобки:

Для вызова событий можно использовать обычный вызов функции, функцию стрелки и привязку.

У функции стрелки отсутствует свой контекст, поэтому внутри данной функции this будет таким же, как и снаружи. При вызове обычной функции внешний контекст this не передаётся и, соответственно, внутри функции нельзя обратиться к параметрам и состоянию компонента. Если это и не требуется, то можно использовать вызов функции без привязки контекста:

Если внутри функции требуется контекст, то используется вызов с привязкой:

Здесь под this понимается контекст родительского компонента, а не дочернего элемента , как может показаться. В методе _onPress компонента невозможно получить значение параметра title элемента . Для ссылки на параметр элемента (дочернего компонента) необходимо получить ссылку на него при помощи атрибута ref, как было показано выше.

Для вызова функции с контекстом и параметрами последние перечисляются после this через запятую:

Пользовательские аргументы передаются функции перед системными. При возникновении события onValueChange система передаёт функции обработки один параметр, в котором находится название выбранной опции компонента Picker. Тогда в первом параметре функции updateUser будет находится строка ‘Привет’, а во-втором — название выбранной опции.

Для уменьшения накладных расходов привязку можно заранее сделать в конструкторе и использовать состояние в качестве параметра:

constructor(props) <
super(props);
this.state = ;
this.updateUser = this.updateUser.bind(this,this.state.name);
>

Обратите внимание на то, что при использовании функции стрелки можно получить оба параметра, передаваемых системой обработчику события onValueChange — название выбранной опции и её индекс, тогда как использовании обычной функции системой передаётся один параметр — название выбранной опции.

При изменении выбранного элемента Picker система вызывает встроенный метод onValueChange. Аналогичным образом в дочернем компоненте можно создать свой метод и затем вызвать его. Для этого создаём метод:

_onMySend = (par) => <
Alert.alert(par)
>

Добавляем его дочернему элементу в качестве параметра, например, onSend:

А где-нибудь в дочернем компоненте вызываем наш метод:

Упростим вызов метода при помощи деструктуризации объекта:

const = this.props;
onSend(‘Параметр 1’)

Параметры props используются не только для хранения в них неизменяемых данных, но и в качестве ссылок на методы. Проще говоря, в элементе:

title и onPress являются параметрами props.

Как динамически добавить или удалить компонент? Для этого можно изменить состояние компонента, сделав его видимым или невидимым, или настроить отображение компонентов в функции отрисовки render(), которая в зависимости от того или иного условия будет отрисовывать нужную компонентную структуру. Разметка в React Native производится при помощи Flexbox.

В основе React Native лежит JavaScript и кажется, что это позволяет использовать такие же трюки и фокусы, как и в web разработке. Но это не так. И на мой взгляд основная сложность фреймворка как раз и заключается в понимании этого. На JavaScript объекты, методы и свойства можно создавать «на лету», есть возможность напрямую взаимодействовать со свойствами и др., а здесь используется традиционный подход к разработке приложений, при котором работа происходит в рамках определённой компонентной структуры, а не динамически создаваемой и загружаемой, как в web среде.

H Пишем нативные модули в React Native в черновиках Tutorial


.collapse»>Содержание

Зачем нужны нативные модули?

Нативные модули в кроссплатформенной разработке под мобильники может понадобиться по следующим причинам:

• Доступ до возможностей платформы, почитать из контент-провайдеров на Android или адресную книгу на iOS
• Обернуть третьесторонюю библиотеку для вызова в js
• Обернуть уже существующий код при добавлении в приложение частей на React Native
• Реализация частей, критических к производительности

Примерная схема приложения на React Native

В операционной системе запущено нативное приложение. В нем на низком уровне работают рантайм React Native и код нативных модулей, созданных разработчиком приложения(или библиотек для React Native). Выше уровнем работает React Native Bridge – промежуточное звено между нативным кодом и js. Сам js исполняется внутри JS VM, чью роль исполняет JavaScriptCore. На iOS она предоставляется системой, на Android же приложение тащит ее в виде библиотеки.

Пишем нативный модуль

Под Android

Лирическое отступление 1 – Компоненты Android

Если ваш основной бэкграунд Android – это отступление можно пропустить. Для разработчиков с iOS или React JS. Приложение под Android может содержать следующие компоненты:

  • Activity
  • BroadcastReceiver
  • Service
  • ContentProvider
  • Application

В данном контексте(кхе-кхе) нас конечно интересует только Application. Напомню, что этот компонент и есть обьект самого приложения. Вы можете(а для React Native приложения и должны) реализовать свой класс приложения и реализовать этим классом интерфейс ReactApplication:

Нужно это, чтобы ReactNative узнал о тех нативных пакетах, которые вы хотите использовать. Для этого наш Application должен вернуть экземпляр ReactNativeHost, в котором перечислить список пакетов:

NativeLoggerPackage — этот тот пакет, который мы будем с вами писать. Он будет только логировать переданные в него значения, чтобы сконцентрироваться на процессе создания нативного модуля, а не на фактической функциональности.

Почему нужно, чтобы Application реализовывал ReactApplication? Потому что внутри React Native есть вот такой веселый код:

Теперь реализуем NativeLoggerPackage:

Метода createViewManagers пока не касаемся, а вот createNativeModules должен вернуть список созданных модулей — классов, которые будут содержать методы, которые можно вызвать из js. Давайте создадим NativeLoggerModule:

Модуль должен наследоваться как минимум от BaseJavaModule, если вам не нужен доступ к контексту Android. Если же в нем есть нужда, вам нужен другой базовый класс:

В любом случае, необходимо определить метод getName(), который вернет имя, под которым ваш модуль будет доступен в js, мы увидим это чуть позже.
Теперь давайте наконец создадим метод для js. Делается это с помощью аннотации ReactMethod:

Здесь метод logTheObject становится доступен для вызова из js. Но вряд ли мы хотим просто вызывать методы без параметров, которые ничего не возвращают. Давайте разбираться с аргументами(слева java-типы, справа js):

Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array

Предположим, что в нативный метод мы хотим передать js-обьект. В java будет приходить ReadableMap:

В случае массива будет передаваться ReadableArray, итерация по которому не составляет проблем:

Впрочем, если вы хотите передать первым аргументом обьект, а вторым массив, то тут тоже без сюрпризов:

Как же это добро вызывать из javascript? Нет ничего проще. Первым делом нужно импортнуть NativeModules из корневой библиотеки react-native:

А затем заимпортить наш модуль(помните, мы назвали его NativeLogger ?):

Теперь можно вызывать метод:

Работает! Но постойте, хочется же знать, все ли в порядке, удалось ли записать то, что мы хотели записать. Как насчет возвращаемых значений?

А вот возвращаемых значений у функций из нативных модулей и нет. Придется выкручиваться, передавая коллбэк:

В нативный код будет приходить интерфейс Callback с единственным методом invoke(Object… args). Со стороны js — это просто функция:

К сожалению, в compile-time нет инстурментов сверить параметры коллбэка из нативного кода и функции в js, будьте внимательны.

К счастью, можно пользоваться механизмом промисов, которые в нативном коде поддерживаются интерфейсом Promise:

Тогда вызывать этот код можно используя async/await:

На этом работа по выставлению нативного метода в js в Android завершена. Смотрим на iOS.

Создание нативного модуля в iOS

Первым делом создаем модуль NativeLogger.h :

и его реализацию NativeLogger.m:

RCT_EXPORT_MODULE — это макрос, который регистрирует наш модуль в ReactNative под именем файла, в котором обьявлен. Если это имя в js для вас не очень подходит, вы можете его поменять:

Теперь давайте реализуем методы, которые делали для Android. Для этого нам понадобятся параметры.

Для обьявления метода можно использовать макрос RCT_EXPORT_METHOD:

Самое интересное тут конечно поддержка промисов. Для этого придется воспользоваться другим макросом RCT_REMAP_METHOD, который первым аргументом принимает имя метода для js, а вторым и последующими — уже сигнатуру метода в objective-c.
Вместо интерфейса, тут передаются два аргумента, RCTPromiseResolveBlock для резолва промиса и RCTPromiseRejectBlock для реджекта:

На этом все. Механизм передачи событий из нативных модулей в js мы рассмотрим в отдельной статье.

Нюансы

Помните, что основная идея нативных модулей — абстракция операционной системы для кроссплатформенного кода. Это значит, что интерфейс модуля должен быть согласован между Android и iOS. Автоматических средств это контролировать я, к сожалению, не знаю.

  • Помните, что по отдельности js и нативный код работают быстро. Бриджинг же между ними относительно медленный. Не стоит писать js циклы, в которых вызывать нативный модуль — перенесите цикл в натив.
  • Уроки React Native

    Уроки React Native

    1. Введение и установка
    2. Стилизация мобильного приложения
    3. Flexbox для начинающих

    Парочка статей по теме:

    — Полезные советы для написания приложения на React Native
    https://proglib.io/p/tips-react-native/

    — 25 понятных туториалов для изучения React Native
    https://proglib.io/p/react-native-tutorials/

    Эта статья была автоматически добавлена из сообщества Библиотека программиста

    Добавить комментарий