-
13. 스택 네비게이터를 이용하여 네비게이션하기프로젝트/할일목록 앱 (RN) 2023. 10. 26. 11:58728x90
/** * @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 컴포넌트로 이동한다.
랜딩페이지 로그인버튼 랜딩페이지 로그인 버튼 클릭시 화면전환 728x90'프로젝트 > 할일목록 앱 (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