/**
* @format
*/
import {AppRegistry} from 'react-native';
import stackRouter from './stackRouter';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => stackRouter);
루트 디렉토리의 index.js 파일을 위와 같이 수정한다. LandingScreen 대신에 stackRouter 컴포넌트를 화면에 보여준다.
import React, { useState, useEffect } from 'react'
import { View, Text, StyleSheet, ActivityIndicator } from 'react-native'
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import LandingScreen from './screens/LandingScreen';
import App from './App'
const Stack = createNativeStackNavigator()
function stackRouter(){
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName = "Landing"
screenOptions={{headerShown: false}} // 탭메뉴 헤더와 겹치지 않도록 함
>
<Stack.Screen name="Landing" component={LandingScreen}/>
<Stack.Screen name="App" component={App}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default stackRouter
루트 디렉토리에 stackRouter 컴포넌트를 생성하고 위와 같이 작성한다.
import LandingScreen from './screens/LandingScreen';
import App from './App'
랜딩페이지와 App 컴포넌트를 임포트한다.
<NavigationContainer>
<Stack.Navigator
initialRouteName = "Landing"
screenOptions={{headerShown: false}} // 탭메뉴 헤더와 겹치지 않도록 함
>
<Stack.Screen name="Landing" component={LandingScreen}/>
<Stack.Screen name="App" component={App}/>
</Stack.Navigator>
</NavigationContainer>
랜딩페이지와 App 컴포넌트는 스택 네비게이터를 이용하여 페이지 전환을 할 수 있도록 설정해준다.
import React from 'react'
import { View, Button, StyleSheet } from 'react-native'
function LoginButton({navigation}){
const gotoHome = () => {
navigation.navigate('App')
}
return (
<View style={styles.buttonWrapper}>
<Button title="로그인" onPress={gotoHome}/>
</View>
)
}
export default LoginButton
const styles = StyleSheet.create({
buttonWrapper: {
position: 'absolute',
left: 0, right: 0,
bottom: 100,
}
})
components > LoginButton.js 파일을 생성하고 위와 같이 작성한다. 로그인 버튼을 화면에 보여주고, 소셜로그인 기능을 수행할 수 있는 컴포넌트이다. 로그인 버튼을 터치하면 LandingScreen 컴포넌트로부터 전달받은 navigation 객체를 이용하여 탭메뉴가 있는 App 컴포넌트로 이동한다. 이때 navigate 메서드로 전달되는 문자열은 Stack.Screen 컴포넌트에 설정된 name 과 동일한 값이다. 로그인 버튼은 position 을 'absolute' 로 설정하여 화면 바닥에서 100dp 떨어진 위치에 보여준다.
import React, { useState } from 'react'
import { SafeAreaView, View, Text, StyleSheet, StatusBar, ScrollView, Dimensions, ImageBackground } from 'react-native'
import LandingPage from '../components/LandingPage'
import landingData from '../data/landingData'
import LoginButton from '../components/LoginButton';
function LandingScreen({navigation}){
const { width, height } = Dimensions.get('window')
const [currentPageIndex, setCurrentPageIndex] = useState(0)
console.log('페이지 번호: ', currentPageIndex)
const setCurrentPage = (e) => {
const { x } = e.nativeEvent.contentOffset // x : 스크롤 위치
console.log("스크롤 위치: ", x, "화면너비: ", width)
const nextPageIndex = Math.ceil(x / width) // x / width : 스크롤 위치 / 화면너비 -> 페이지번호
console.log(nextPageIndex)
if(nextPageIndex !== currentPageIndex){
setCurrentPageIndex(nextPageIndex)
}
}
return (
<>
<StatusBar hidden></StatusBar>
<SafeAreaView style={styles.block}>
<ScrollView
style={{ flex: 1 }}
horizontal={true} // 수평 스크롤링
scrollEventThrottle={16} // 스크롤 이벤트 감지하는 시간간격 (ms)
pagingEnabled={true} // 스크롤시 페이지네이션
showsHorizontalScrollIndicator={false} // 스크롤바 숨기기
onScroll={setCurrentPage}
>
{landingData.map((page, index) => (
<LandingPage
width={width}
height={height}
{...page}
key={index}
/>
))}
</ScrollView>
<View style={styles.scrollIndicatorWrapper}>
{Array(3).fill(0).map((_, index) => (
<View key={index} style={[styles.scrollIndicator, { opacity: currentPageIndex === index ? 1: 0.3}]}></View>
))}
</View>
<LoginButton navigation={navigation}/>
</SafeAreaView>
</>
)
}
const styles = StyleSheet.create({
block: {
flex: 1
},
scrollIndicatorWrapper:{
position: 'absolute',
left: 0, right: 0,
bottom: 50,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center'
},
scrollIndicator: {
height: 10,
width: 10,
borderRadius: 10 / 2,
backgroundColor: '#aaa',
marginLeft: 10,
},
})
export default LandingScreen
screens > LandingScreen.js 파일을 위와 같이 수정한다.
import LoginButton from '../components/LoginButton';
랜딩페이지에서 사용자가 로그인할 수 있도록 loginButton 컴포넌트를 임포트한다.
<LoginButton navigation={navigation}/>
loginButton 컴포넌트에서 navigation 객체를 이용할 수 있도록 props 로 내려준다. LoginButton 컴포넌트는 스택 네비게이터에 정의되어 있지 않기 때문에 기본적으로 navigation 객체를 전달받지 못한다. 그래서 사용하려면 LandingScreen 컴포넌트에서 전달받아서 내려줘야 한다.
export default function App({navigation}) {
// 중략
}
App.js 파일에 해당 부분을 수정한다. App 컴포넌트는 스택 네비게이터에 정의되어 있으므로 navigation 객체를 전달받고 사용할 수 있다.
<NavigationContainer>
// 중략
</NavigationContainer>
App.js 의 해당 부분을 아래와 같이 Fragment 컴포넌트로 변경한다. 이렇게 하는 이유는 이미 스택 네비게이터를 사용할때 NavigationContainer 로 감싸주었기 때문에 App 컴포넌트에서 다시 NavigationContainer 를 사용하면 에러가 발생한다.
<>
// 중략
</>
* 페이지 전환 테스트하기
랜딩페이지의 로그인 버튼을 클릭하면 스택 네비게이터에 정의된 App 컴포넌트로 이동한다.
'프로젝트 > 할일목록 앱 (RN)' 카테고리의 다른 글
14. 구글폰트 적용하기 - 랜딩페이지 문구 변경 (0) | 2023.10.26 |
---|---|
15. LoginButton 컴포넌트에 소셜 로그인 기능 구현하기 (0) | 2023.10.26 |
12. 랜딩페이지 구현하기 (0) | 2023.10.25 |
11. 설정화면 - 구글 로그인 이후 사용자 프로필 보여주기 (0) | 2023.10.25 |
10. 소셜로그인 - 구글 로그인 (0) | 2023.10.24 |