Инженер-программист ReactJS может плавно перейти на изучение Swift и SwiftUI. Для этого нужно найти соответствия знакомых концепций в новой среде разработки. В данном руководстве мы рассмотрим аналоги распространенных шаблонов ReactJS в Swift и SwiftUI.
Примечание. Есть масса способов решить задачу. В данном случае примеры в виде небольших фрагментов кода иллюстрируют общие концепции.
Для дальнейших экспериментов и работы с примерами рекомендую скачать Playground с GitHub.
Инициализация проекта
Начать новый проект React можно разными способами. Один из них — использовать create-react-app
:
npx create-react-app my-app
cd my-app
npm start
В Swift для создания нового проекта SwiftUI применяется Xcode
:
- Открываем
Xcode
. - Выбираем
Create a new Xcode project
(“Создать новый проектXcode
”). - Сначала выбираем
iOS
(илиmacOS
, илиMultiplatform
), затемApp
и далееSwiftUI
в качестве опцииinterface
.
Структурирование компонентов
Компоненты — это строительные блоки UI приложения.
В React компоненты часто представляют из себя функции, которые возвращают JSX
:
const Greeting = () => <h1>Hello, world!</h1>;
В SwiftUI компоненты называются представлениями (англ. View). Их определяют как структуры, соответствующие протоколу View
:
struct Greeting: View {
var body: some View {
Text("Hello, world!")
}
}
Получение входных данных формы
Как правило, любое приложение выполняет обработку пользовательского ввода.
ReactJS
В React вы создаете поле для ввода и с помощью хука useState
отслеживаете его значения:
const InputComponent = () => {
const [inputValue, setInputValue] = useState("");
const handleChange = event => setInputValue(event.target.value);
return <input type="text" value={inputValue} onChange={handleChange} />;
};
SwiftUI
SwiftUI упрощает данный процесс. С помощью обертки свойства @State
и привязки ее к вводу он выполняет синхронизацию:
struct InputView: View {
@State private var inputValue = ""
var body: some View {
TextField("Enter text", text: $inputValue)
.padding()
}
}
Использование состояния
Состояние имеет важное значение для реактивных пользовательских интерфейсов.
ReactJS
В React для управления состоянием компонентов часто задействуется хук useState
:
const Counter = () => {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
};
SwiftUI
Аналогичным образом в SwiftUI применяется обертка свойства @State
для отслеживания локального состояния представления:
struct CounterView: View {
@State private var count = 0
var body: some View {
Button("Clicked \(count) times") {
count += 1
}
.padding()
}
}
Передача обратных вызовов дочерним компонентам
Передача функций в качестве входных параметров (англ. props) — обычная практика в процессе взаимодействия родительских и дочерних компонентов.
ReactJS
В React через входные параметры вы передаете функцию дочернему компоненту, который ее вызывает:
const Parent = () => {
const handleAction = () => console.log("Action handled");
return <Child onAction={handleAction} />;
};
const Child = ({ onAction }) => <button onClick={onAction}>Do Action</button>;
SwiftUI
В SwiftUI этот процесс осуществляется путем передачи замыканий дочерним представлениям:
struct ParentView: View {
var body: some View {
ChildView(onAction: { print("Action handled") })
}
}
struct ChildView: View {
let onAction: () -> Void
var body: some View {
Button("Do Action", action: onAction)
}
}
Совместное использование данных в приложении
Зачастую работа приложения требует обмена данными между различными компонентами.
ReactJS (с Context
)
React предоставляет инструмент Context API
, широко применяемый для совместного использования состояния и передачи его через дерево компонентов. Он избавляет от необходимости передавать входные параметры вручную:
const AppContext = createContext();
const Parent = () => (
<AppContext.Provider value={{ message: "Hello from context" }}>
<Child />
</AppContext.Provider>
);
const Child = () => {
const context = useContext(AppContext);
return <div>{context.message}</div>;
};
SwiftUI (с EnvironmentObject
)
В свою очередь SwiftUI предлагает EnvironmentObject
, позволяющий представлениям совместно использовать общий источник данных:
class AppData: ObservableObject {
@Published var message = "Hello from environment object"
}
struct ParentView: View {
var body: some View {
ChildView().environmentObject(AppData())
}
}
struct ChildView: View {
@EnvironmentObject var appData: AppData
var body: some View {
Text(appData.message)
}
}
Обработка побочных эффектов
Реагирование на изменения — важнейшая характеристика работы любого современного UI-фреймворка.
ReactJS (с useEffect
)
В React хук useEffect
позволяет выполнять действия, называемые побочными эффектами, в функциональных компонентах:
const MyComponent = () => {
useEffect(() => {
console.log("Component mounted");
return () => console.log("Component unmounted");
}, []);
return <div>Hello, World!</div>;
};
SwiftUI (с onAppear
и onDisappear
)
SwiftUI предоставляет модификаторы onAppear
и onDisappear
, которые можно добавлять к представлениям для обеспечения аналогичной функциональности:
struct MyView: View {
var body: some View {
Text("Hello, World!")
.onAppear {
print("View appeared")
}
.onDisappear {
print("View disappeared")
}
}
}
Примечание. Модификатор .task
более подходит для вызова асинхронных функций async
при первом отображении представления, чем .onAppear
. Если представление ликвидируется до завершения задачи, то задача автоматически отменяется.
Маршрутизация и навигация
Навигация — это основа любого приложения.
ReactJS (с React Router
)
В React для навигации применяется React Router
:
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const Navigation = () => (
<Router>
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
</ul>
</nav>
<Route path="/" exact component={Home} />
</div>
</Router>
);
SwiftUI (с NavigationView
и NavigationLink
)
SwiftUI предлагает NavigationView
и NavigationLink
для создания навигационных интерфейсов:
struct NavigationExampleView: View {
var body: some View {
NavigationView {
NavigationLink(destination: HomeView()) {
Text("Home")
}
}
}
}
Заключение
SwiftUI предполагает декларативный подход к созданию UI, аналогичный ReactJS, но более тесно интегрированный с Swift.
Установив соответствия между ReactJS и SwiftUI, вы сможете легко перейти с одного инструмента на другой. Конечно, потребуется время для освоения новых знаний, но понимание сходств и различий в шаблонах сделает процесс обучения более плавным.
SwiftUI очень быстро развивается, поэтому целесообразно отслеживать новейшие изменения и функциональности.
Читайте также:
- Реактивное программирование с Combine
- React Native: полное руководство по созданию виджета для домашнего экрана для iOS и Android
- Выбор лучшего фреймворка для создания мобильного приложения
Читайте нас в Telegram, VK и Дзен
Перевод статьи Drew Althage: A Few Code Examples for Reactjs Engineers Learning Swift and SwiftUI