Совместное использование кода в приложениях React и React Native



Книга Совместное использование кода в приложениях React и React Native

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


Некоторые продвинутые команды уже создают полноценную кроссплатформенную систему проектирования с помощью React и React Native (видеоурок).


Аккордеон React-Native, который мы создадим; для веб-приложения у нас будет также аккордеон React

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


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


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



Здесь можно найти (и использовать) все компоненты из этого руководства.



Итак, погрузимся в процесс.


1. Два компонента: React и React Native


Нам предстоит работа с двумя аккордеонами  —  одним для React, другим для React Native.


Вот компонент аккордеона React.



Изучите и установите/откройте его, чтобы протестировать локально или отредактировать.


Другой компонент  —  React Native.



Уделите пару секунд изучению графа “зависимости” каждого компонента. Согласитесь, у них много общих зависимостей.


Общие зависимости компонентов React и React Native

2. Превращение общего кода в общие зависимости


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


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


Вот зависимости компонентов, которые нужно создать и скомпоновать с аккордеонами React и React Native (можно найти их все здесь):


share-react-react-native              --> scope
├── api --> namespace
│ ├── accordion --> component
│ └── accordion-items --> component
├── design-tokens --> namespace
│ ├── base-tokens --> component
│ ├── react-tokens --> component
│ └── rnative-tokens --> component
├── base-ui --> namespace
│ ├── hooks --> namespace
│ │ ├── use-open --> component
│ │ └── use-select --> component
│ ├── react --> namespace
│ │ └── accordion --> component
│ └── react-native --> namespace
│ └── accordion --> component
└── theme --> namespace
├── web --> component
└── mobile --> component

3. Добавление зависимостей в платформенно-ориентированные компоненты


Между React и React Native есть различия. Например, они не допускают применения одинаковых свойств и типов стилей. Если все размерности в React Native не имеют единиц измерения, то в React можно использовать px, rem, em и т.д.


Для выполнения нашей задачи понадобятся базовый объект с наиболее общими значениями и платформенно-ориентированные компоненты с дополнительными свойствами.


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



  • Базовый токен  —  общий для обоих:


export interface BaseTokensProps {
primaryColor: string;
secondaryColor: string;
borderColor: string;
borderStyle: "solid" | "dotted" | "dashed" | undefined;
}

export const baseTokens: BaseTokensProps = {
primaryColor: "red",
secondaryColor: "blue",
borderColor: "green",
borderStyle: "solid",
};


  • Токен, дополняющий базовый для использования с React:


import { baseTokens } from "@learnbit-react/web-mobile-design-system.design-tokens.base-tokens";
import type { BaseTokensProps } from "@learnbit-react/web-mobile-design-system.design-tokens.base-tokens";

export interface ReactTokensProps extends BaseTokensProps {
spacing: string;
fontSize: string;
borderWidth: string;
}

export const reactTokens: ReactTokensProps = {
...baseTokens,
spacing: "15px",
fontSize: "18px",
borderWidth: "3px",
};


  • Токен, дополняющий базовый для использования с React Native:


import { baseTokens } from "@learnbit-react/web-mobile-design-system.design-tokens.base-tokens";
import type { BaseTokensProps } from "@learnbit-react/web-mobile-design-system.design-tokens.base-tokens";

export interface RNativeTokensProps extends BaseTokensProps {
spacing: number;
fontSize: number;
borderWidth: number;
}

export const rNativeTokens: RNativeTokensProps = {
...baseTokens,
primaryColor: "purple",
secondaryColor: "gray",
spacing: 10,
fontSize: 12,
borderWidth: 3,
};


Если в вашей среде разработки выполняется автозаполнение местоположения посредством относительного импорта, можете быстро исправить это, выполнив команду bit link — rewire.



4. Предоставление тем для React и React Native


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


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


$ bit install @teambit/base-react.theme.theme-provider

Нам понадобится объект tan со свойствами темы. Вызовем функцию createTheme, указав ее в качестве аргумента. Результатом будет объект с хуком для использования этих значений и компонент, который осуществляет ввод с помощью React Context.



import { createTheme } from "@teambit/base-react.theme.theme-provider";

import { reactTokens } from "@learnbit-react/web-mobile-design-system.design-tokens.react-tokens";
import type { ReactTokensProps } from "@learnbit-react/web-mobile-design-system.design-tokens.react-tokens";

const theme = createTheme<ReactTokensProps>({
theme: reactTokens,
});

const { useTheme, ThemeProvider } = theme;
export { useTheme, ThemeProvider };


  • А вот и тема для React Native. Передадим опцию withoutCssVars: true, чтобы избежать необходимости рендеринга <div>.


import { createTheme } from "@teambit/base-react.theme.theme-provider";

import { rNativeTokens } from "@learnbit-react/web-mobile-design-system.design-tokens.rnative-tokens";
import type { RNativeTokensProps } from "@learnbit-react/web-mobile-design-system.design-tokens.rnative-tokens";

const theme = createTheme<RNativeTokensProps>({
theme: rNativeTokens,
withoutCssVars: true,
});

const { useTheme, ThemeProvider } = theme;

export { useTheme, ThemeProvider };

Предоставим темы аккордеонам. Теперь это просто сделать: можно импортировать компоненты-темы.


Оба аккордеона будут иметь одинаковый каркас, где мы используем хуки и получаем в качестве возврата соответствующий список, как показано в этом фрагменте:


import { useTheme } from '@learnbit-react/web-mobile-design-system.theme.web // or .mobile in the react-native one!
import { useOpen } from '@learnbit-react/web-mobile-design-system.hooks.use-open';
import { useSelect } from '@learnbit-react/web-mobile-design-system.hooks.use-select';
import type { AccordionProps } from '@learnbit-react/web-mobile-design-system.api.accordion';

const GenericAccordionTemplate = ({ elementList } : AccordionProps) => {
const { isOpen, toggleOpen } = useOpen();
const { selectedId, setSelection } = useSelect();
const {someValueToken, someValueToken} = useTheme();

return <div_or_View style={{someProp: someValueToken}}>My styled element<div_or_View/>;
};


Обратите внимание, что аккордеоны не используют один и тот же хук useTheme. Каждый из них использует свой хук в соответствии с заданными типами стилей.



5. Создание веб- и мобильного приложений с общими зависимостями


Наконец пришло время создать веб- и мобильное приложения с использованием новых компонентов и общих зависимостей. В компонуемых приложениях (т.е. с Bit) всегда есть возможность добавить компонент и развернуть его. Поскольку здесь все является компонентом, можно добавить компонент для развертывания в Netlify или создать/добавить любые аналогичные компоненты для развертывания в любом месте. Подробнее здесь.


Веб-приложение React


Вот конечный резульат развертывания в Netlify. Посмотрим, как это сделать.


Создадим компонент приложения и установим Netlify. 


$ bit create react-app apps/react/accordion — scope learnbit-react.web-mobile-design-system

bit install react-router-dom

bit use learnbit-react.web-mobile-design-system/apps/react/accordion

bit install @teambit/cloud-providers.deployers.netlify

Теперь добавим аккордеон в код приложения.


import React from "react"; 
import { Routes, Route } from "react-router-dom";
import { Accordion } from "@learnbit-react/web-mobile-design-system.base-ui.react.accordion";
import { Item } from "@learnbit-react/web-mobile-design-system.api.accordion"; export function AccordionApp() {
return (
<>
{/* header component */}
<Routes>
<Route
path="/"
element={
<Accordion
elementList={[
new Item("Asia", "01").toObject(),
new Item("Africa", "02").toObject(),
new Item("North America", "03").toObject(),
new Item("South America", "04").toObject(),
new Item("Antarctica", "05").toObject(),
new Item("Australia / Oceania", "06").toObject(),
new Item("Europe", "07").toObject(),
]}
/>
}
/>
<Route path="/about">{/* about page component */}</Route>
</Routes>
{/* footer component */}
</>
);
}

Путем настройки приложения в accordion.react-app.ts и запуска bit tag, получим его снапшот и развернем его:


bit tag apps/react/accordion -m “First deploy”

Наконец оно развернуто!


Использование компонента React Native в Expo


expo init my-new-project 

cd my-new-project

yarn install @learnbit-react/web-mobile-design-system.base-ui.react-native.accordion @learnbit-react/web-mobile-design-system.api.accordion

Добавим компонент в файл app.js:


import {Accordion} from '@learnbit-react/web-mobile-design-system.base-ui.react-native.accordion';
import { Item } from '@learnbit-react/web-mobile-design-system.api.accordion';

import {(StyleSheet, View)} from 'react-native';

export default function App() {
return (
<View style={styles.container}>
<Accordion
elementList={[
new Item('Asia', '01').toObject(),
new Item('Africa', '02').toObject(),
new Item('North America', '03').toObject(),
new Item('South America', '04').toObject(),
new Item('Antarctica', '05').toObject(),
new Item('Australia / Oceania', '06').toObject(),
new Item('Europe', '07').toObject(),
]}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start',
marginTop: 50,
},
});

Вот исходный код на GitHub.


Вывод


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



513   0  

Comments

    Ничего не найдено.