React Native + Expo で開発を始めて画面遷移させるまで
Expo のインストール
npm i -g expo-cli
React Native のプロジェクトを作成
expo init my-first-react-native-app
✔ Choose a template: › blank (TypeScript) same as blank but with TypeScript configuration
- cd my-first-react-native-app
- yarn start # you can open iOS, Android, or web from here, or run them directly with the commands below.
- yarn android
- yarn ios
- yarn web
ビルドサーバーを起動してアプリを動かす
npm start
Developer tools running on http://localhost:19002
というコメントが表示された後、http://localhost:19002
をブラウザで開く。
iOS のシミュレータを動かそうとして、以下のようなエラーが出た場合。
› Opening on iOS...
xcrun exited with non-zero code: 2
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=2):
Unable to boot device because we cannot determine the runtime bundle.
No such file or directory
下記の対応を行い、npm start
→ キーボードの i
を押下 で解消できる。
xcode を立ち上げ -> Xcode メニュー -> Open Developer Tool -> Simulator でシミュレータを立ち上げたら、シミュレータメニューの Device -> Erase all content and settings でセッティングをクリア。
xcode をアップデートしたら expo で iOS シミュレータが起動できなくなった
React Native Paper をセットアップ
React Native 向けに開発された UI ライブラリで、Material Design に準拠している。
npm i react-native-paper
ルートディレクトリにある babel.config.js
を以下のように修正する。
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
env: {
production: {
plugins: ['react-native-paper/babel']
}
}
};
};
サンプルを動かす
ここまで作ってきた環境を使って、以下のような画面を動かしてみる。
作るのは以下の 3 つ。
App.tsx
lib/components/Main.tsx
lib/components/MyCard.tsx
import { Provider as PaperProvider } from 'react-native-paper'
import Main from './lib/components/Main'
export default function App() {
return (
<PaperProvider>
<Main />
</PaperProvider>
)
}
import React from 'react'
import { Button, Headline, Title } from 'react-native-paper'
import { SafeAreaView, ScrollView } from 'react-native'
import MyCard from './MyCard'
const Main = () => (
<SafeAreaView>
<ScrollView>
<Headline
style={{
margin: 15,
}}
>
色んなパーツをごちゃまぜ
</Headline>
<Title
style={{
margin: 15,
}}
>
タイトルだよ〜
</Title>
<Button
mode={'contained'}
style={{
margin: 30,
}}
>
containedなボタン
</Button>
<MyCard />
</ScrollView>
</SafeAreaView>
)
export default Main
import * as React from 'react'
import { Avatar, Button, Card, Title, Paragraph } from 'react-native-paper'
import { ReactNode } from 'react'
const LeftContent = (props: ReactNode) => <Avatar.Icon {...props} icon="folder" />
const MyCard = () => (
<Card
style={{
margin: 20,
}}
>
<Card.Title title="Card Title" subtitle="Card Subtitle" left={LeftContent} />
<Card.Content>
<Title>Card title</Title>
<Paragraph>Card content</Paragraph>
</Card.Content>
<Card.Cover source={{ uri: 'https://picsum.photos/700' }} />
<Card.Actions>
<Button>Cancel</Button>
<Button>Ok</Button>
</Card.Actions>
</Card>
)
export default MyCard
ここまで触ってみて、React + SwiftUI = React Native のような印象を受けた。
React と SwiftUI 両方の経験があるとキャッチアップしやすいように思えた。
画面遷移を実装する
ベースとなるライブラリのインストール。
npm i @react-navigation/native
expo install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
左右にスライドして画面を切り替えるパターン(Stack Navigator)
ボタンクリックで 右 → ← 左 と画面が切り替わっていく画面の作り方。
npm i @react-navigation/stack
初期画面
ボタンクリックで移動する。
※Disconnected from Metro
は気にしないでください。
コードをいじるのは以下の 3 ファイル。
App.tsx
lib/components/HomeScreen.tsx
lib/components/DetailScreen.tsx
import 'react-native-gesture-handler'
import { NavigationContainer } from '@react-navigation/native'
import HomeScreen from './lib/components/HomeScreen'
import { createStackNavigator } from '@react-navigation/stack'
import DetailScreen from './lib/components/DetailScreen'
export type RootStackParamList = {
Home: undefined
Detail: undefined
}
const Stack = createStackNavigator()
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName={'Home'}>
<Stack.Screen name={'Home'} component={HomeScreen} />
<Stack.Screen name={'Detail'} component={DetailScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
import * as React from 'react'
import { Text, View, Button } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { RootStackParamList } from '../../App'
type homeScreenProp = StackNavigationProp<RootStackParamList, 'Home'>
const HomeScreen = () => {
const navigation = useNavigation<homeScreenProp>()
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text>ホーム画面</Text>
<Button title={'詳細へ'} onPress={() => navigation.navigate('Detail')} />
</View>
)
}
export default HomeScreen
import * as React from 'react'
import { View, Text, Button } from 'react-native'
import { useNavigation } from '@react-navigation/native'
const DetailScreen = () => {
const navigation = useNavigation()
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text>詳細画面</Text>
<Button title={'ホームへ'} onPress={() => navigation.goBack()} />
</View>
)
}
export default DetailScreen
参考
エラー対応
以下のようなnavigation.navigate
で...
<Button title={"詳細へ"} onPress={() => navigation.navigate("Detail")} />
以下のようなエラーが出た場合
TS2345: Argument of type 'string' is not assignable to parameter of type '{ key: string; params?: undefined; merge?: boolean | undefined; } | { name: never; key?: string | undefined; params: never; merge?: boolean | undefined; }'.
こちらの StackOverflow を参考に解消した。
navigation.navigate('Home') showing some error in typescript
タブで切り替えるパターン(Tab Navigator)
npm i @react-navigation/bottom-tabs
修正は App.tsx
のみ。
import 'react-native-gesture-handler'
import { NavigationContainer } from '@react-navigation/native'
import HomeScreen from './lib/components/HomeScreen'
+ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import DetailScreen from './lib/components/DetailScreen'
export type RootStackParamList = {
Home: undefined
Detail: undefined
}
+ const Tab = createBottomTabNavigator()
export default function App() {
return (
<NavigationContainer>
+ <Tab.Navigator initialRouteName={'Home'}>
+ <Tab.Screen name={'Home'} component={HomeScreen} />
+ <Tab.Screen name={'Detail'} component={DetailScreen} />
+ </Tab.Navigator>
</NavigationContainer>
)
}
Author And Source
この問題について(React Native + Expo で開発を始めて画面遷移させるまで), 我々は、より多くの情報をここで見つけました https://zenn.dev/fjsh/articles/5d91c01fb17a19著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol