expo를 전역에 설치한 후 프로젝트를 생성한다.
npm install --global expo-cli
expo init "프로젝트 이름"
깃허브에 연결한다.
앱은 유저가 보기전에 준비되어 있어야한다. 따라서 preload를 해줘야한다.
<AppLoading/>
태그 사용을 위한 패키지
npm install expo-app-loading
startAsync - 로딩 중 실행되는 함수
onError - 에러가 나면 실행되는 함수
onFinish - 로딩이 끝나면 실행되는 함수 (promise를 리턴한다.
폰트사용을 위한 패키지
npm install expo-font
loadAsync를 통해서 이미지를 preload하는데 asset이 필요하다.
expo install expo-asset
//App.js
export default function App() {
const [loading, setLoading] = useState(true);
const onFinish = () => setLoading(false);
const preload = () => {
const fontsToLoad = [Ionicons.font];
const fontPromises = fontsToLoad.map((font) => Font.loadAsync(font));
const imagesToLoad = [
require("./assets/logo.png"),
"https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Instagram_logo.svg/840px-Instagram_logo.svg.png",
];
const imagePromises = imagesToLoad.map((image) => Asset.loadAsync(image));
return Promise.all([...fontPromises, ...imagePromises]);
}
if (loading) {
return (
<AppLoading
startAsync={preload}
onError={console.warn}
onFinish={onFinish}
/>
);
}
네비게이션은 route역할을 한다.
네비게이션을 만들기 위한 패키지를 다운 받는다.
npm install @react-navigation/native
제스쳐에 관한 패키지
expo install react-native-gesture-handler
애니메이션에 관한 패키지
expo install react-native-reanimated
스크린에 관한 패키지
expo install react-native-screens
아이폰의 맨 위 가운데 부분을 위한 패키지
expo install react-native-safe-area-context
component의 색깔을 꾸며주는 패키지
expo install @react-native-community/masked-view
Navigation은 세가지 종류가 있다.
1. 스택(stack)
2. 탭스(tabs)
3. 드로어(drawer)
스택
npm install @react-navigation/stack
스택은 모든 이전 페이지를 기억한다.
스택관련 공식문서에서 여러 props들을 보고 사용할 수 있다.
Stack.Navigator에서는 모든 screen의 option을 설정할 수 있다.
Stack.Screen은 각 스크린의 option을 설정한다.
//LoggedOutNav.js
const Stack = createStackNavigator();
export default function LoggedOutNav() {
return (
<Stack.Navigator screenOptions={{
headerBackTitleVisible: false,
}}>
<Stack.Screen
name="Welcome"
options={{
headerShown: false,
}}
component={Welcome} />
<Stack.Screen
name="Login"
component={Login} />
<Stack.Screen
options={{
title: false,
headerTransparent: true,
headerTintColor: "white",
}}
name="CreateAccount"
component={CreateAccount}
/>
</Stack.Navigator>
);
}
Screen은 여러 props를 넘길 수 있어 다른 component에서 사용할 수 있다.
import React from "react";
import { Text, View, TouchableOpacity } from "react-native";
export default function Welcome({ navigation }) {
return (
<View>
<Text>Welcome</Text>
<TouchableOpacity onPress={() => navigation.navigate("CreateAccount")}>
<View>
<Text>Gogogo</Text>
</View>
</TouchableOpacity>
</View>
);
}
navigation은 반드시 NavigationContainer로 감싸줘야한다.
//App.js
return (
<NavigationContainer>
<LoggedOutNav />
</NavigationContainer>
);
react-native의 TextInput은 많은 props를 가지고 있다.
returnKeyType은 핸드폰 키보드의 엔터키를 바꿔준다.
onSubmitEditing은 엔터키를 누를 시 실행하는 함수이다.
이 때 onNext함수를 보면 Ref를 인자로 받아와서 focus해준다.
current는 받아온 Ref를 뜻한다.
KeyboardAvoidingView를 이용하여 키보드가 나왔을 때 component들이 위로 밀려 키보드가 가리지 않게 해준다.
//CreateAccount.js
export default function CreateAccount() {
const lastNameRef = useRef();
const usernameRef = useRef();
const emailRef = useRef();
const passwordRef = useRef();
const onNext = (nextOne) => {
nextOne?.current?.focus();
};
const onDone = () => {
alert("done!");
};
return (
<AuthLayout>
<KeyboardAvoidingView
style={{
width: "100%"
}}
behavior="padding"
keyboardVerticalOffset={Platform.OS === "ios" ? 30 : 0}
>
<TextInput
placeholder="First Name"
placeholderTextColor="gray"
returnKeyType="next"
style={{ backgroundColor: "white", width: "100%" }}
onSubmitEditing={() => onNext(lastNameRef)}
/>
<TextInput
ref={lastNameRef}
placeholder="Last Name"
placeholderTextColor="gray"
returnKeyType="next"
style={{ backgroundColor: "white", width: "100%" }}
onSubmitEditing={() => onNext(usernameRef)}
/>
.
.
.
키보드가 아닌 다른 곳을 터치했을 때 키보드가 사라지도록 한다.
//AuthLayout.js
export default function AuthLayout({ children }) {
const dismissKeyboard = () => {
Keyboard.dismiss();
};
return (
<TouchableWithoutFeedback style={{ height: "100%" }} onPress={dismissKeyboard}>
<Container>
<Logo resizeMode="contain" source={require("../../assets/logo.png")} />
{children}
</Container>
</TouchableWithoutFeedback>
);
}