經過前面 13 天的奮戰,我們位於 GCP 雲端的 AI 大腦已經準備就緒,不僅能精準吐出 JSON 格式的馬拉松課表,還有完善的資安與流量防護。
現在,我們要開始打造跑者每天都會打開的手機 APP——「KAKERU」。
為什麼不寫原生的 Swift (iOS) 或 Kotlin (Android)?因為在這短時間的開發時間,我期望能同樣達到開發效率、維護成本降低、學習新應用。因此 React Native 成為我的最佳解。第一是能讓我比較無痛用 TypeScript 編譯雙平台的 Native 元件來撰寫 APP,二來是支援 iOS 跟 Android 生態系、最後是能夠學習到 APP 的應用。
但在敲下第一行 Code 之前,如果還帶著寫 Web 的舊思維來寫 APP,保證會處處碰壁。今天,我們就來進行三個最重要的觀念轉換,並帶你用 AI 最快的方式把專案跑起來!
在 Web 開發中,能夠很熟悉地打出 <div>、<span>、<button>。但在 React Native 的世界裡,沒有瀏覽器,也沒有 DOM。
我們寫的 JavaScript 元件,會在執行時被橋接(Bridge)轉譯成 iOS / Android 底層的真正原生 UI 元件。因此,你必須改用 React Native 提供的核心元件:
| Web (網頁思維) | React Native (手機思維) | 說明與差異 |
|---|---|---|
<div> |
<View> |
最基礎的容器元件,用來包裝其他元件與排版。 |
<p>, <span>, <h1> |
<Text> |
極度重要:在 RN 裡,所有的純文字「必須」包在 <Text> 裡面,否則程式會直接報錯崩潰! |
<button> |
<Pressable> / <TouchableOpacity> |
處理使用者的點擊與手勢。TouchableOpacity 點擊時會有原生的半透明回饋感。 |
<img> |
<Image> |
顯示圖片。注意:載入網路圖片時,必須強制指定 width 與 height。 |
<input> |
<TextInput> |
讓使用者輸入文字(例如我們之後要填寫的跑者身高體重表單)。 |
在 React Native 中,樣式是透過 JavaScript 物件來定義的,並且使用 StyleSheet.create() 來管理。
最重要的兩個排版觀念差異:
background-color 變成了 backgroundColor。flexDirection 預設是 row (橫向排列);但在手機螢幕這種長條形的裝置上,React Native 的 flexDirection 預設是 column (直向排列)!所有元素天生都會由上往下疊加。這可能會是是 Web 開發者最常踩的兩個坑:
在網頁上,內容超過視窗高度瀏覽器會自動生出卷軸。但在 React Native 中,超出螢幕底部的部分就永遠消失了!
解法:遇到需要滾動的內容,必須明確使用 <ScrollView> 或是針對長列表優化的 <FlatList>。
如果單純使用 <View>,文字很可能會被手機上方的時間電量圖示或是攝影機瀏海擋住。
解法:在頁面的最外層使用 <SafeAreaView>,系統會自動幫你避開瀏海。
只要電腦有安裝 Node.js,打開終端機,執行以下步驟:
建立名為 Kakeru-AI-App 的專案
# 建立名為 Kakeru-AI-App 的專案
npx create-expo-app@latest Kakeru-AI-App
# ##進入專案資料夾
cd Kakeru-AI-App
# 啟動開發伺服器
npx expo start
執行後,終端機會出現一個 QR Code。這時,請確認你的實體手機與電腦連線至同一個 Wi-Fi 網路。接著,到應用程式商店下載「Expo Go」APP(iOS 或 Android 皆可),打開 APP 掃描畫面上的 QR Code,你就能立刻在自己的手機上看到出爐的 React Native 畫面,完全不需要接傳輸線!
既然我們的主題是「AI 輔助開發」,我們當然不會從零開始手刻畫面!我們要像是開發後端一樣,直接寫一段 Prompt 給 Antigritivy,就能請他生成:
「我正在使用 React Native 搭配 Expo 開發一個名為 KAKERU 的馬拉松 AI 教練 APP。 請幫我寫一個首頁元件 (Home Screen)。
設計需求:
- 畫面最上方要有大標題『歡迎回到 KAKERU』,以及副標題『AI 教練已經為您準備好本週課表』。
- 下方需要一個主按鈕,文字為『查看課表』,背景顏色請用亮橘色 (#FF5722)。
- 整體風格要現代、乾淨,背景使用淺灰色。
技術限制:
- 必須使用
SafeAreaView包裝最外層,避免被手機瀏海擋住。- 按鈕請使用
TouchableOpacity。- 樣式必須統一寫在底部的
StyleSheet.create中。」
產出的程式碼與結果如下:
import React from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
StatusBar,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useRouter } from 'expo-router';
export default function HomeScreen() {
const router = useRouter();
.
.
.
});
並且就可以得到以下的畫面:
原先以為是簡單的「掃QR Code看畫面」,在實際開發中卻經常會遇到各種邊緣狀況。這次我們在初始化時就接連遇到了三個新手(我)必踩的大坑,所幸透過 AI 協助,在幾分鐘內迅速排除了所有問題:
package.json 精準降級到 SDK 54 相容版本,並透過 -legacy-peer-deps 解決了 React 19 與 Expo 各模組之間的 peerDependency 衝突。expo-dev-client 造成的「找不到可用的資料」
expo-dev-client 套件。當該套件存在時,Expo 會預設切換為「原生開發版 (Dev Build)」模式,產生的 QR Code 無法被標準的 Expo Go 識別。AI 協助清理套件並重啟後,Expo 順利切換回 › Using Expo Go 模式!Element type is invalid ... TabLayout)
Element type is invalid... Check the render method of TabLayout 報錯,手機也因此跟著閃退。_layout.tsx 中的 ThemeProvider 錯從 expo-router 匯入(正確應來自 @react-navigation/native),並同步修正了模板中不相容的 SF Symbols 與原生 Tabs 語法,執行 npx tsc --noEmit 達到 0 Error!心得:遇到環境與套件版本地獄時,不要慌張,把錯誤訊息完整丟給 AI,它能精準揪出根本原因並直接幫你完成代碼修復!
今天我們正式跨足 Mobile 開發領域,打通了從 Web 到 React Native 的觀念!不僅說明了 <View>、<Text> 與 StyleSheet 等手機端的排版差異,化解了環境衝突,更透過強大的 Expo 與 AI Prompt,在實體手機上成功跑出了 KAKERU 的第一個精美畫面。
不過讀者應該已經發現了,畫面的底部已經長出了一個非常有質感的懸浮導覽列 (Bottom Tabs)!
既然 AI 已經幫我們把骨架搭好了,明天(Day 15)將一起了解背後的路由黑作法:Expo Router (或 React Navigation)。我們不僅要了解它是如何運作的,還要親手調校這個導覽列,實作跨頁面的基礎設定,讓跑者能在「首頁」、「課表頁」與「個人設定」之間流暢穿梭。敬請期待!