Необходимые условия для библиотек¶
Внимание
Эта документация все еще является экспериментальной, и детали могут быть изменены по мере итераций. Не стесняйтесь делиться своими отзывами в обсуждении внутри рабочей группы для этой страницы.
Более того, она содержит несколько ручных шагов. Пожалуйста, обратите внимание, что это не будет представлять окончательный опыт разработчиков, когда Новая архитектура станет стабильной. Мы работаем над инструментами, шаблонами и библиотеками, которые помогут вам быстро начать работу с новой архитектурой без необходимости проходить всю процедуру настройки.
Следующие шаги помогут обеспечить готовность ваших модулей и компонентов к новой архитектуре.
Определите спецификации в JavaScript¶
Спецификации JavaScript служат источником истины для методов, предоставляемых каждым родным модулем. Они определяют все API, предоставляемые родным модулем, а также типы этих констант и функций.
Использование типизированного файла спецификации позволяет вам быть преднамеренным и объявить все входные аргументы и выходы методов вашего родного модуля.
Поддержка TypeScript сейчас находится в бета-версии.
Чтобы перейти на новую архитектуру, начните с создания этих спецификаций для ваших родных модулей и родных компонентов. Вы можете сделать это до перехода на новую архитектуру: спецификации будут использоваться позже для генерации кода нативного интерфейса для всех поддерживаемых платформ как способ обеспечения единообразия API на разных платформах.
Turbo Native Modules¶
Файлы спецификаций JavaScript должны иметь имя Native<MODULE_NAME>.js
, и они экспортируют объект Spec
реестра TurboModuleRegistry
. Соглашение об имени важно потому, что процесс Codegen ищет модули, чей файл спецификации js
(jsx
, ts
или tsx
) начинается с ключевого слова Native
.
Ниже приведен базовый шаблон спецификации JavaScript, написанный с использованием синтаксиса Flow и TypeScript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Fabric Native Components¶
Файлы спецификаций JavaScript должны иметь имя <FABRIC COMPONENT>NativeComponent.js
(для TypeScript используйте расширение .ts
или .tsx
) и экспортировать объект HostComponent
. Соглашение об имени важно: процесс Codegen ищет компоненты, чей файл спецификации (JavaScript или TypeScript) заканчивается суффиксом NativeComponent
.
Следующий фрагмент показывает базовый шаблон спецификации JavaScript, написанный на Flow, а также TypeScript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
Поддерживаемые типы¶
При использовании Flow или TypeScript вы будете использовать type annotations для определения спецификации. Учитывая, что целью определения спецификации JavaScript является обеспечение типобезопасности генерируемого кода родного интерфейса, набор поддерживаемых типов будет состоять из тех, которые могут быть сопоставлены один к одному с соответствующим типом на родной платформе.
В общем случае это означает, что вы можете использовать примитивные типы (строки, числа, булевы), типы функций, типы объектов и типы массивов. Союзные типы, с другой стороны, не поддерживаются. Все типы должны быть доступны только для чтения. Для Flow: либо +
, либо $ReadOnly<>
, либо {||}
объекты. Для TypeScript: readonly
для свойств, Readonly<>
для объектов и ReadonlyArray<>
для массивов.
См. приложение II. Сопоставление потоковых типов с нативными типами.
См. приложение III. Сопоставление TypeScript с нативными типами.
Вспомогательные типы Codegen¶
Вы можете использовать предопределенные типы для своих JavaScript-спецификаций, вот их список:
Double
Float
Int32
UnsafeObject
WithDefault<Type, Value>
— Устанавливает значение по умолчанию для типаBubblingEventHandler<T>
— Для событий, которые распространяются (bubbled) вверх по дереву компонентов от дочернего компонента к родительскому вплоть до корня (например:onStartShouldSetResponder
).DirectEventHandler<T>
— Для событий, которые вызываются только на элементе, получающем событие (например:onClick
) и не распространяются.
Позже эти типы компилируются в соответствующие эквиваленты на целевых платформах.
Быть последовательным на разных платформах и устранить неоднозначность типов¶
Прежде чем внедрять новую архитектуру в свой родной модуль, вы должны убедиться, что ваши методы согласованы между платформами. Вы поймете это, когда приступите к написанию спецификации JavaScript для вашего родного модуля — помните, что спецификация JavaScript определяет, как будут выглядеть методы на всех поддерживаемых платформах.
Если в вашем существующем родном модуле есть методы с одинаковым именем на нескольких платформах, но с разным количеством или типом аргументов на разных платформах, вам нужно будет найти способ сделать их согласованными. Если у вас есть методы, которые могут принимать два или более различных типов для одного и того же аргумента, то вам нужно найти способ разрешить этот тип двусмысленности, поскольку объединения типов намеренно не поддерживаются.
Убедитесь, что автолинкинг включен¶
Autolinking — это функция React Native CLI, которая упрощает установку сторонних библиотек React Native. Инструкции по включению autolinking доступны в React Native CLI docs.
Android¶
На Android для этого обычно требуется включить native_modules.gradle
в settings.gradle
и build.gradle
.
Если вы использовали шаблон по умолчанию, поставляемый с React Native (т.е. yarn react-native init <Project>
), то автолинковка уже включена.
Вы можете проверить, включена ли она, используя:
1 2 3 4 5 |
|
Если вы этого не сделали, откройте файл settings.gradle
и добавьте эту строку:
1 2 |
|
Затем откройте файл android/app/build.gradle
и добавьте эту строку в конец файла:
1 |
|
iOS¶
На iOS убедитесь, что ваша библиотека предоставляет Podspec (пример см. в react-native-webview
).
Чтобы определить, настроена ли ваша библиотека на автолинковку, проверьте вывод CocoaPods после выполнения команды pod install
(или arch -x86_64 pod install
в случае Mac M1) в проекте iOS. Если вы увидите "auto linking library name", то все готово к работе.
Настройте Codegen¶
Codegen — это инструмент, который запускается при сборке приложения для Android или установке зависимостей приложения для iOS. Он создает некоторый код, который вам не придется создавать вручную.
Codegen можно настроить в файле package.json
вашей Библиотеки. Добавьте в его конец следующий объект JSON.
1 2 3 4 5 6 7 8 9 10 |
|
- Поле
codegenConfig
— это ключ, используемый Codegen для проверки наличия кода для генерации. - Поле
name
— это имя библиотеки. - Поле
type
используется для определения типа модуля, который мы хотим создать. Мы рекомендуем оставитьall
для поддержки библиотек, содержащих как Turbo Native Module, так и Fabric Native Components. - Поле
jsSrcsDir
— это каталог, в котором codegen начнет искать спецификации JavaScript. android.javaPackageName
— это имя пакета, в который попадает сгенерированный код.
Android также требует, чтобы в вашем приложении был правильно настроен React Gradle Plugin.
Миграция с JavaScript API UIManager
.¶
В новой архитектуре большинство методов UIManager
станут доступны как методы экземпляра для нативных экземпляров компонентов, полученных через ref
:
1 2 3 4 5 6 7 8 9 10 11 |
|
Этот новый дизайн API обеспечивает несколько преимуществ:
- Улучшение эргономики разработчика за счет отсутствия необходимости отдельно импортировать
UIManager
или вызыватьfindNodeHandle
. - Более высокая производительность благодаря отсутствию шага поиска узлового хэндла.
- Согласован по направлению с аналогичной депривацией
findDOMNode
.
В конечном счете мы устареем UIManager
. Однако мы признаем, что миграции требуют больших затрат для многих авторов приложений и библиотек. Чтобы минимизировать эти затраты, мы планируем продолжать поддерживать как можно больше методов UIManager
в новой архитектуре.
Поддержка методов UIManager
в новой архитектуре активно разрабатывается. Пока мы делаем успехи, ранние пользователи могут экспериментировать с новой архитектурой, выполнив следующие шаги по миграции с общих API UIManager
:
- Миграция с
setNativeProps
. - Перенести вызов
requireNativeComponent
в отдельный файл - Перенос
dispatchViewManagerCommand
. - Создание NativeCommands с помощью
codegenNativeCommands
Перенос setNativeProps
¶
setNativeProps
не будет поддерживаться в пост-фабричном мире. Для перехода переместите все значения setNativeProp
в состояние компонента.
Пример.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
В этом примере при нажатии кнопки View происходит вызов setNativeProps
для обновления пропсов стиля и доступности компонента. Чтобы перенести этот компонент, важно понять его текущее поведение с помощью setNativeProps
.
Pre-Fabric, пропсы компонента сохраняются¶
При первом рендере пропсы компонента — это пропсы, объявленные в функции рендеринга. После нажатия кнопки View _onSubmit
вызывает setNativeProps
с обновленными значениями пропсов.
Результирующий компонент может быть представлен следующим образом:
1 2 3 4 5 6 7 |
|
Обратите внимание, что все значения пропсов, установленные в функции рендеринга, остаются неизменными, даже если setNativeProps
не передал эти пропсы. Кроме того, style
теперь является объединенным значением своего значения до _onSubmit
и styles.submittedView
. Это важный момент: в нашем текущем мире, предшествующем миру Fabric, компонентные пропсы сохраняются. Представление платформы кэширует значения пропсов, переданные ему со стороны JS. Если бы это было не так, то после вызова setNativeProps React Native отобразил бы компонент следующим образом:
1 |
|
Тот факт, что React Native хранит некоторое внутреннее состояние каждого компонента, которое не объявлено явно в последнем рендере, — это то, что Fabric намерена исправить.
Перемещение setNativeProps
в состояние¶
Принимая во внимание вышеуказанные предостережения, правильный перенос будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
- Мы используем флаг
hasSubmitted
, чтобы показать, хотим ли мы применитьstyles.submittedView
или нет. Если стиль был динамическим, то имеет смысл хранить объект стиля в состоянии. - Флаг
accessibility
теперь явно передается компоненту View в виде булевой величины. Это отличается от предыдущей реализации, гдеaccessibility
не передавалось в качестве параметра при первоначальном рендере, но в этом случае мы знаем, что неуказаниеaccessibility
обрабатывается так же, как иaccessibilty={false}
.
Будьте осторожны в своих предположениях, так как не пойманные тонкости могут внести различия в поведение! Хорошей идеей будет провести моментальные тесты вашего компонента, так как они выявят любые различия до и после миграции.
Перенесите вызов requireNativeComponent
в отдельный файл.¶
Это позволит подготовить JS к новой системе codegen для новой архитектуры. Новый файл должен быть назван <ComponentName>NativeComponent.js.
.
Старый способ¶
1 2 3 4 5 |
|
Новый путь¶
RNTMyNativeNativeComponent.js | |
---|---|
1 2 3 4 5 |
|
RNTMyNativeViewNativeComponent.js | |
---|---|
1 2 3 4 5 6 7 |
|
Поддержка Flow¶
Если requireNativeComponent
не типизирован, вы можете временно использовать mixed
тип, чтобы исправить предупреждение Flow, например:
1 2 3 4 5 6 7 |
|
Позже вы сможете заменить requireNativeComponent
.¶
Когда вы будете готовы к переходу на Fabric, вы можете заменить requireNativeComponent
на codegenNativeComponent
:
RNTMyNativeViewNativeComponent.js | |
---|---|
1 2 3 4 5 |
|
И обновите основной файл:
RNTMyNativeNativeComponent.js | |
---|---|
1 2 3 4 |
|
Переход от dispatchViewManagerCommand
.¶
Как и в предыдущем случае, в попытке избежать вызова методов UIManager, все методы менеджера представлений теперь вызываются через экземпляр NativeCommands
. codegenNativeCommands
— это новый API для генерации кода NativeCommands
на основе интерфейса команд вашего менеджера представлений.
До
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Создание нативных команд с помощью codegenNativeCommands
MyCustomMapNativeComponent.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Примечание:
- Первым аргументом команды
moveToRegion
является ссылка на HostComponent нативного компонента. - Аргументы команды
moveToRegion
перечислены в сигнатуре. - Определение команды располагается вместе с родным компонентом. Это поощряемый шаблон
- Убедитесь, что вы включили имя своей команды в массив
supportedCommands
.
Использование вашей команды¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Обновление нативной реализации¶
В примере сгенерированный код Commands
отправит вызов moveToRegion
в менеджер представлений нативного компонента. В дополнение к написанию JS-интерфейса, вам нужно будет обновить сигнатуры нативной реализации, чтобы они соответствовали диспетчеризированному вызову метода. Для справки смотрите отображение для типов аргументов Android и типов аргументов iOS.
iOS
1 2 3 4 5 6 |
|
Android
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|