시작하자마자 냅다 코드 던저버리기
import React from 'react';
import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert } from 'react-native';
export default function DetailPage() {
const tip = {
"idx":9,
"category":"재테크",
"title":"렌탈 서비스 금액 비교해보기",
"image": "https://storage.googleapis.com/sparta-image.appspot.com/lecture/money1.png",
"desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ",
"date":"2020.09.09"
}
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 styles = StyleSheet.create({
container:{
backgroundColor:"#000"
},
image:{
height:400,
margin:10,
marginTop:40,
borderRadius:20
},
textContainer:{
padding:20,
justifyContent:'center',
alignItems:'center'
},
title: {
fontSize:20,
fontWeight:'700',
color:"#eee"
},
desc:{
marginTop:10,
color:"#eee"
},
button:{
width:100,
marginTop:20,
padding:10,
borderWidth:1,
borderColor:'deeppink',
borderRadius:7
},
buttonText:{
color:'#fff',
textAlign:'center'
}
})
벨로그에서는 사진을 작게 보이게 할 순 없나 가독성이 넘 떨어지네
3주차 강의 시작하자마자 만들라고 해서 만들긴 했는데 보여주기 좋지 못해서 그냥 복붙한 거 올려요.. Sorry..
만들다보니 이제 페이지 하나 정도는 만들 수 있겠다 싶었어요..
페이지화에 대해 배우려고 여러 js파일을 만드는 과정임다
카드 컴포넌트를 components 폴더에 만듬
카드 하나하나 만들었던 긴 코드를 주석으로 바꾸고 return에 Card 컴포넌트 하나만을 사용해서 카드를 보여주게 함 (변수 이름, 속성키 이름은 마음대로 해도 됨)
Card.js 확인! 카드 하나하나를 모듈화 (컴포넌트화) 해서 메인 코드 화면에 길었던 코드들이 간결해졌고 코드들은 Card.js에 들어가 있음
useEffect
에 넣음const [state,setState] = useState([])
useState
에서는 실제 컴포넌트에서 사용할 데이터state
와 그 데이터를 변경하거나 수정할 때 쓰는 setState
두 가지를 전달해줌useEffect(()=>{setState(data)},[])
이 뒤에 있는 setState
를 통해서 data.json에 있는 데이터를 준비시키고 있는 것을 알 수 있음? 에러가 생기는 이유는 ?
const [state,setState] = useState([])
useState
는 초기값을 전달해주는 함수 (빈 리스트)state
에 담기게 됨 (컴포넌트 안에서 사용할 상태변수)state
에 담긴 데이터를 수정하려면 항상 setState
함수를 이용해서 변경해야됨> useEffect(()=>{setState(data)},[])
setState 안에 data를 전달하는 것을 볼 수 있음
-> state 안에 data가 담기게 됨
tip
에다가 state.tip
을 실행하려고 하고 있음tip
이라는 딕셔너리가 없음 (state
의 상태변수가 빈 리스트, 키 없음)! 해결 !
Loading.js
를 만들어 코드가 준비될 때까지 보여주게 함MainPage.js
에import Loading from '../components/Loading';
하고return ready ? <Loading/> :
를 통해 로딩 화면이 한 번 그려지게 되고 useEffect
가 실행이 됨> useEffect(()=>{
setTimeout(()=>{
setState(data)
setReady(false)
},1000)
},[])
data를 담고 로딩화면을 걷어내기 위해 ready의 값을 true에서 false로 변경하여 data의 화면을 보여주게 함
너무 너무 너무 어려운 부분인 것 같다.. 강의 5번은 넘게 돌려본듯 ㅜ
const [ready,setReady] = useState(true)
useEffect(()=>{
setTimeout(()=>{
//메인 페이지 컴포넌트에서 항상 가지고 있을 꿀팁 전체 데이터
setState(data.tip)
//카테고리 버튼을 누르는 거 마다 달라질 상태변수
setCateState(data.tip)
//로딩화면 걷어내는 것
setReady(false)
},1000)
},[])
기존 코드는 비슷하고 onPress
에 어떤 함수가 바인딩 되어 있는 지가 중요함
-> category
함수가 실행 되게끔 바인딩 되어 있음
category
함수 확인
-> cate
라는 변수를 넘겨받고 있음
-> .fliter
함수를 사용
('생활'카테고리를 눌렀을 때 category
함수가 실행됨
-> cate=='생활'이 되고 '전체보기'가 아니기 때문에 else문이 실행되게 됨
-> 요소 하나하나 돌릴 때마다 카테고리의 값이 '생활'이면 그 해당하는 값으로 리스트를 새로 만들어짐
-> CateState에 저장됨)
state
였던 부분이 CateState
라고 변경 되어 있음 (이제 화면에서 보이게 될 상태 변수는 CateState
를 사용하기 때문)
expo install expo-status-bar
StatusBar
import 하기 (import하는 방식은 조금씩 다르니까 공식문서 확인): 리액트 네이티브에서 페이지 간의 이동, 페이지에서 이동할 때 데이터를 가지고 가는 방식
react-navigation 공식 문서
https://reactnavigation.org/
네비게이션 설치 코드
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
스택 네비게이션
: 컴포넌트에 페이지 기능을 부여해주고 컴포넌트에서 컴포넌트로 이동,
즉 페이지 이동을 가능하게 해줌 (책갈피 기능과 유사)
페이지 Stack.Screen
책갈피 Stack.Navigator
creatStackNavigator 설치 코드
yarn add @react-navigation/stack
navigation 폴더를 만들고 StackNavigator.js 파일을 만듬
사용할 코드 분석
1. 사용 준비
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: "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>
{/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣습니다. 이 자체로 이제 페이지 기능을 합니다*/}
<Stack.Screen name="MainPage" component={MainPage}/>
<Stack.Screen name="DetailPage" component={DetailPage}/>
StackNavigator에 코드 넣기
App.js 코드 확인하고 실행화면
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>);
}
항상 return 으로 한 페이지만 바꿔서 볼 수 있었는데 return에 다양한 코드들이 들어가 있음
컨텐츠 윗 부분에 MainPage라는 이름이 띄워져 있음
MainPage가 써져 있는 코드를 확인해볼 수 있음
screenOptions
를 사용해서 공통적인 정보를 보여주게 설정할 수 있음
메인 페이지에서 특정한 카드 버튼을 누르면 다른 페이지로 넘어가게 됨
페이지를 이동시키려면, 책갈피가 페이지들에게 부여해준 페이지 이동 기능을 사용해야함
Stack.screen
에 등록된 모든 페이지 컴포넌트들은 navigation
와 route
라는 딕셔너리(객체)를 속성으로 넘겨받아 사용할 수 있음
//navigation 객체가 가지고 있는 두 함수(setOptions와 navigate)
//해당 페이지의 제목을 설정할 수 있음
navigation.setOptions({
title:'나만의 꿀팁'
})
//Stack.screen에서 name 속성으로 정해준 이름을 지정해주면 해당 페이지로 이동하는 함수
navigation.navigate("DetailPage")
//name 속성을 전달해주고, 두 번째 인자로 딕셔너리 데이터를 전달해주면, Detail 페이지에서
//두번째 인자로 전달된 딕셔너리 데이터를 route 딕셔너리로 로 받을 수 있음
navigation.navigate("DetailPage",{
title: title
})
//전달받은 데이터를 받는 route 딕셔너리
//비구조 할당 방식으로 route에 params 객체 키로 연결되어 전달되는 데이터를 꺼내 사용
//navigate 함수로 전달되는 딕셔너리 데이터는 다음과 같은 모습이기 때문입니다.
/*
{
route : {
params :{
itle:title
}
}
}
*/
const { title} = route.params;
어떻게 사용하는 지 알 수 있는 코드 전혀 모르겠음
실습해보기
MainPage.js
에서 바뀐 코드
export default function MainPAge({navigation,route})
를 보면 navigation
딕셔너리랑 route
딕셔너리를 비구조 할당 방식으로 바로 받아서 사용할 준비를 함
Stack.Screen
에서 component={MainPage}
메인 페이지를 컴포넌트와 연결해 페이지화 당하면 두 가지 딕셔너리를 쓸 수 있는 데(페이지화된 애들한테만 쓸 수 있음) 그게 위의 navigation
과 route
이고 이 메인 페이지에 두 가지 딕셔너리를 넘겨주고 있다는 것을 알 수 있음
카드들도 똑같이 네이게이션을 붙여주면 됨
navigation
과 route
두 가지 딕셔너리는 페이지화된 애들한테만 쓸 수 있는데 네비게이션 도구를 자식 컴포넌트에 넘겨줘서 자식 컴포넌트에도 사용할 수 있음
데이터를 가지고 페이지 이동하기
navigation.navigate("Detail",{
title: title
})
Card.js
코드를 확인하면 카드를 누르면 그 상세 페이지가 컨텐츠와 함께 넘어가게끔 코드를 구현했고
DetailPage.js
또한 페이지화 되어 있으니 navigation, route
를 사용했음
이 코드에서 useEffect
에서 디테일 페이지로 들어갈 때마다 위의 제목을 원래 카드 제목으로 띄울 수 있게 변경하기 위해 setOptions
를 사용함 (route.params.
에는 Card.js
로부터 넘겨받은 데이터가 들어 있기 때문에 사용함)
import {Share} from "react-native";
Share.share
함수에 공유하고 싶은 내용을 딕셔너리 형태의 메세지 키에 물려주면 외부에 해당 내용을 공유할 수 있음DetailPage.js
에 있는 글의 출처를 바로가기 버튼을 사용해 만들 예정expo install expo-linking
터미널에서 설치 후DetailPage,js
에서 import * as Linking from 'expo-linking';
을 해줌Linking
을 사용하여 전화 버튼을 누르면 바로 통화할 수 있게 만들어주는 환경도 만들 수 있음)어바웃 화면 페이지화 시키고 버튼 추가하기
TouchableOpacity
를 사용해서 버튼을 만들고 박스 스타일은 middleButtonAll
을 사용하여 기본의 버튼과 동일하게 만드려다가 크기가 약간 달라 topButton
을 통해 만들었음 (그 안에 텍스트는 기존과 동일해서 middleButtonTextAll
을 사용해서 만듬)onPress
에 navigation.navigate('AboutPage')
를 해뒀음 (
import AboutPage from '../pages/AboutPage';
를 해주고 <Stack.Screen name="AboutPage" component={AboutPage}/>
을 똑같이 적어두었더니 어설프지만 '메인 페이지'에서 '소개 페이지' 버튼을 눌렀을 때 'AboutPage'가 바로 나옴import {useEffect} from 'react'
를 하고 상단의 '소개 페이지'가 적힌 부분을 수정할 수 있게 useEffect
를 씀headerTitleStyle
을 만들었음<StatusBar style="light" />
이게 있었는데 본 코드와 큰 차이가 없는 거 같아 일단 적지 않았음, 그래서 위에 import { StatusBar } from 'expo-status-bar';
부분이 흐림으로 표시됨import * as Linking from 'expo-linking';
를 하고 link
함수를 만들어 인스타 계정 주소를 적고 기존의 코드에 onPress={()=>link()}
를 추가함꿀팁 찜 페이지가 화면을 만들기
이상하네 아무리 해도 안돼
어머 보기만 해도 어렵네? 어쩌겠어 해내야지
차차 해서 올려야지..