terminal
expo install expo-status-bar
Js
import {StatusBar} from 'expo-status-bar'
<StatusBar style = "light"/>
import React from 'react'
import MainPage from './pages/MainPage'
import DetailPage from './pages/DetailPage'
export default function App(){
return(<MainPage/>)
//return(<DetailPage/>)
//return (<AboutPage/>)
}
-> 컴포넌트들 간의 이동을 자유롭게 해줄 수 있다.
import React from 'react';
//이제 모든 페이지 컴포넌트들이 끼워져있는 책갈피를 메인에 둘예정이므로
//컴포넌트를 더이상 불러오지 않아도 됩니다.
// import MainPage from './pages/MainPage';
// import DetailPage from './pages/DetailPage';
import { StatusBar } from 'expo-status-bar';
//메인에 세팅할 네비게이션 도구들을 가져옵니다.
import {NavigationContainer} from '@react-navigation/native';
import StackNavigator from './navigation/StackNavigator'
export default function App() {
console.disableYellowBox = true;
return (
<NavigationContainer>
<StatusBar style="black" />
<StackNavigator/>
</NavigationContainer>);
}
yarn add @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
yarn add @react-navigation/stack
https://reactnavigation.org/docs/stack-navigator/
import React from 'react';
//설치한 스택 네비게이션 라이브러리를 가져옵니다
import { createStackNavigator } from '@react-navigation/stack';
//페이지로 만든 컴포넌트들을 불러옵니다
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';
//스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용합니다
//그래서 이렇게 항상 상단에 선언하고 시작하는게 규칙입니다!
const Stack = createStackNavigator();
const StackNavigator = () =>{
return (
//컴포넌트들을 페이지처럼 여기게끔 해주는 기능을 하는 네비게이터 태그를 선언합니다.
//위에서 선언한 const Stack = createStackNavigator(); Stack 변수에 들어있는 태그를 꺼내 사용합니다.
//Stack.Navigator 태그 내부엔 페이지(화면)를 스타일링 할 수 있는 다양한 옵션들이 담겨 있습니다.
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "black",
borderBottomColor: "black",
shadowColor: "black",
height:100
},
headerTintColor: "#FFFFFF",
headerBackTitleVisible: false
}}
>
{/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣습니다. 이 자체로 이제 페이지 기능을 합니다*/}
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
</Stack.Navigator>
)
}
export default StackNavigator;
사용 준비
import React from 'react'; //설치한 스택 네비게이션 라이브러리를 가져옵니다 import { createStackNavigator } from '@react-navigation/stack'; //페이지로 만든 컴포넌트들을 불러옵니다 import DetailPage from '../pages/DetailPage'; import MainPage from '../pages/MainPage'; //스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용합니다 //그래서 이렇게 항상 상단에 선언하고 시작하는게 규칙입니다! const Stack = createStackNavigator();
기본 틀
const StackNavigator = () =>{ return ( //페이지 기능이 들어가는 곳 ) } export default StackNavigator;
스크린 옵션
//위에서 선언한 const Stack = createStackNavigator(); Stack 변수에 들어있는 태그를 꺼내 사용합니다. //Stack.Navigator 태그 내부엔 페이지(화면)를 스타일링 할 수 있는 다양한 옵션들이 담겨 있습니다. <Stack.Navigator screenOptions={{ //공통적으로 적용될 헤더의 스타일 headerStyle: { backgroundColor: "white", borderBottomColor: "white", shadowColor: "white", height:100 }, //헤더의 텍스트를 왼쪾에 둘지 가운데에 둘지를 결정 headerTitleAlign:'left', //헤더 text 색상 headerTintColor: "#000", headerBackTitleVisible: false }} > {/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣습니다. 이 자체로 이제 페이지 기능을 합니다*/} <Stack.Screen name="MainPage" component={MainPage}/> <Stack.Screen name="DetailPage" component={DetailPage}/> </Stack.Navigator>
페이지화
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
책갈피화
<Stack.Navigator> ~'페이지화 등록'~ </Stack.Navigator>
사용하기
NavigationContainer로 묶어서 '책'으로 반환한다.
APP.js
export default function App() {
console.disableYellowBox = true;
return (
<NavigationContainer>
<StatusBar style="black" />
<StackNavigator/>
</NavigationContainer>);
}
navigation을 통해 page가 된 컴포넌트들은 두가지 속성을 지닌다.
export default function MainPage({navigation,route})
제목변경
navigation.setOptions({ title:'원하는 제목' }
이동하기
navigation.navigate("Stack.screen에서 name속성으로 정해준 이름")
구조
//전달받은 데이터를 받는 route 딕셔너리 //비구조 할당 방식으로 route에 params 객체 키로 연결되어 전달되는 데이터를 꺼내 사용 //navigate 함수로 전달되는 딕셔너리 데이터는 다음과 같은 모습이기 때문입니다. /*{ route : { params :{ title:title } } }*/ const { title} = route.params;
전달하기
//name 속성을 전달해주고, 두 번째 인자로 딕셔너리 데이터를 전달해주면, Detail 페이지에서 //두번째 인자로 전달된 딕셔너리 데이터를 route 딕셔너리로 로 받을 수 있음 navigation.navigate("DetailPage",{ title: title })
ex)MainPage.js
useEffect(()=>{
//제목 변경
navigation.setOptions({
title:'나만의 꿀팁'
})
//뒤의 1000 숫자는 1초를 뜻함
//1초 뒤에 실행되는 코드들이 담겨 있는 함수
setTimeout(()=>{
//헤더의 타이틀 변경 / 밖에 존재해도 상관없음
// navigation.setOptions({
// title:'나만의 꿀팁'
// })
setState(data.tip)
setCateState(data.tip)
setReady(false)
},1000)
ex)MainPage.js
cateState.map((content,i)=>{
return (<Card content={content} key={i} navigation={navigation}/>)
})
ex)Card.js
import React from 'react';
import {View, Image, Text, StyleSheet,TouchableOpacity} from 'react-native'
//MainPage로 부터 navigation 속성을 전달받아 Card 컴포넌트 안에서 사용
export default function Card({content,navigation}){
return(
//카드 자체가 버튼역할로써 누르게되면 상세페이지로 넘어가게끔 TouchableOpacity를 사용
<TouchableOpacity style={styles.card} onPress={()=>{navigation.navigate('DetailPage',content)}}>
<Image style={styles.cardImage} source={{uri:content.image}}/>
<View style={styles.cardText}>
<Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
<Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
<Text style={styles.cardDate}>{content.date}</Text>
</View>
</TouchableOpacity>
)
}
ex)DetailPage.js
import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert } from 'react-native';
export default function DetailPage({navigation,route}) {
//초기 컴포넌트의 상태값을 설정 -> loading페이지를 활용해도 됨.
//초기 값이 없으면 error -> 들어가자마자 데이터가 없으면 그릴 수 없으므로.
//state, setState 뿐 아니라 이름을 마음대로 지정할 수 있음!
const [tip, setTip] = useState({
"idx":9,
"category":"재테크",
"title":"렌탈 서비스 금액 비교해보기",
"image": "https://storage.googleapis.com/sparta-image.appspot.com/lecture/money1.png",
"desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ",
"date":"2020.09.09"
})
useEffect(()=>{
console.log(route)
//Card.js에서 navigation.navigate 함수를 쓸때 두번째 인자로 content를 넘겨줬죠?
//content는 딕셔너리 그 자체였으므로 route.params에 고대~로 남겨옵니다.
//즉, route.params 는 content죠!
navigation.setOptions({
//setOptions로 페이지 타이틀도 지정 가능하고
title:route.params.title,
//StackNavigator에서 작성했던 옵션을 다시 수정할 수도 있습니다.
headerStyle: {
backgroundColor: '#000',
shadowColor: "#000",
},
headerTintColor: "#fff",
})
setTip(route.params)
},[])
const popup = () => {
Alert.alert("팝업!!")
}
return (
// ScrollView에서의 flex 숫자는 의미가 없습니다. 정확히 보여지는 화면을 몇등분 하지 않고
// 화면에 넣은 컨텐츠를 모두 보여주려 스크롤 기능이 존재하기 때문입니다.
// 여기선 내부의 컨텐츠들 영역을 결정짓기 위해서 height 값과 margin,padding 값을 적절히 잘 이용해야 합니다.
<ScrollView style={styles.container}>
<Image style={styles.image} source={{uri:tip.image}}/>
<View style={styles.textContainer}>
<Text style={styles.title}>{tip.title}</Text>
<Text style={styles.desc}>{tip.desc}</Text>
<TouchableOpacity style={styles.button} onPress={()=>popup()}><Text style={styles.buttonText}>팁 찜하기</Text></TouchableOpacity>
</View>
</ScrollView>
)
}
const share = () => {
Share.share({
message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
});
}
<TouchableOpacity style={styles.button} onPress={()=>share()}><Text style={styles.buttonText}>팁 공유하기</Text></TouchableOpacity>
expo install expo-linking
const link = () => {
Linking.openURL("https://https://velog.io/@yoon_s_whan")
}
<TouchableOpacity style={styles.button} onPress={()=>link()}><Text style={styles.buttonText}>외부 링크</Text></TouchableOpacity>