티스토리 뷰
3-3-----------------------------------------------------------------------------------------------------------
import React from 'react' import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native'; export default function Main_page() { console.disableYellowBox = true; const tip = { "idx":9, "category":"재테크", "title":"렌탈 서비스 금액 비교해보기", "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Frental.png?alt=media&token=97a55844-f077-4aeb-8402-e0a27221570b", "desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ", "date":"2020.09.09" } return ( <ScrollView style={styles.background}> <Image style={styles.image} source={{uri:tip.image}}/> <View style={styles.text_container}> <Text style={styles.top_text}>{tip.title}</Text> <Text style={styles.mid_text}>{tip.desc}</Text> <TouchableOpacity style={styles.touchop}><Text style={styles.op_text}>팁 찜하기</Text></TouchableOpacity> </View> </ScrollView> ); } const styles = StyleSheet.create({ background:{ backgroundColor:'black', }, image:{ marginTop:40, marginLeft:30, margin:10, width:300, height:400, borderRadius:20 }, text_container:{ padding:20, justifyContent:'center', alignItems:'center' }, top_text:{ margin:10, color:'#fff', fontSize:30, fontWeight:'700', }, mid_text:{ margin:10, color:'#fff', fontSize:16, fontWeight:'500', }, touchop:{ width:100, padding:10, borderWidth:1, borderRadius:7, margin:10, borderColor:'deeppink', backgroundColor:'black' }, op_text:{ fontSize:15, color:'#fff', textAlign:'center' } }); |
=>왜 내껀 글이 가운데 정렬이 안되는거지
=>top_text 글자가 크기 커서 안된거임..
-----------------------------------------------------------------------------------------------------------------------------------
3-4-------------------------------------------------------------------------------------------------------------------------------
리액트 기초 지식
-컴포넌트: 정해진 요소들을 (<>얘들)을 사용하여 만든 화면의 일부분, 그냥 화면의 일부분임
화면을 작게 쪼개기때문에 유지보수가 편하게 해줌
-상태 state: 컴포넌트에서 데이터를 유지하고 관리하기 위한 유일한 방법
-속성 props: 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 방식(style={styles.어쩌고})
-useEffect: 화면에 컴포넌트가 그려지면 처음 실행해야 하는 함수를 모아두는곳, 어플이 켜지면 가장 먼저 실행되는 함수

import로 다른 폴더의 혹은 뭐 암튼 js파일을 불러오면 해당 js파일의 함수를 호출가능

map을 통해 i번 반복하여 i번째 딕셔너리를 content로 하여 Card()에 인자로 전달(props), Card함수에서는 해당 content를 받아 컴포넌트를 만들고(컴포넌트화) Main_page로 return
-----------------------------------------------------------------------------------------------------------------------------------
3-5-------------------------------------------------------------------------------------------------------------------------------
속성
<>안에서 그 태그의 속성을 정해준것

-----------------------------------------------------------------------------------------------------------------------------------
3-6-------------------------------------------------------------------------------------------------------------------------------
상태에 대해
-상태가 변해야 화면이 변한다.
-리액트 네이티브는 실시간으로 화면이 변하는 기능에 최적화
useEffect
-리액트 기본 제공 함수
useEffect(()=>{ ...화면이 그려진 다음 가장 먼저 실행되야 할 코드 작성 공간 },[]) |
-가장 먼저 실행되어야 할 로직을 여기다 넣는다
지금까지는 단순히 변수에 값을 담아서 사용했으므로 상태가 변한것은 아니다
상태를 변화하고 이를 반영하기 위해서는 useState를 사용해야 된다
import React,{useState,useEffect} from 'react'; . . . const [state,setState] = useState([state에 들어갈 리스트]) |
useState는 함수로 state, setState를 반환한다
state는 상태가 저장되는 변수이고 setState는 그 상태를 관리하는 함수이다.
setState를 이용해 관리하는것을 useEffect함수 안에서 한다
-----------------------------------------------------------------------------------------------------------------------------------
3-7-------------------------------------------------------------------------------------------------------------------------------
로딩화면= 데이터를 준비할 시간을 주는것= state에 값 넣을 시간을 주는것
import React,{useState,useEffect} from 'react'; import main from '../assets/main.png'; import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native'; import data from '../data.json'; import Card from '../components/Card'; import Loading from '../components/Loading'; export default function MainPage() { console.disableYellowBox = true; //return 구문 밖에서는 슬래시 두개 방식으로 주석 const [state,setState] = useState([]) //컴포넌트에 상태를 여러개 만들어도 됨 //관리할 상태이름과 함수는 자유자재로 정의할 수 있음 //초기 상태값으로 리스트, 참거짓형, 딕셔너리, 숫자, 문자 등등 다양하게 들어갈 수 있음. const [ready,setReady] = useState(true)//로딩이 완료되었는지 여부를 저장하는 상태 //준비중에 있을때는 true 완료되면 false useEffect(()=>{ //뒤의 1000 숫자는 1초를 뜻함 //1초 뒤에 실행되는 코드들이 담겨 있는 함수 setTimeout(()=>{ setState(data)//setState를 실행 위에서 import한 data를 넣어 state에 넣는다 setReady(false)//위의 setState가 끝나면 ready는 false },1000) },[]) let tip = state.tip;//위에서 state에 data를 넣었으므로 사용가능 let todayWeather = 10 + 17; let todayCondition = "흐림" //처음 ready 상태값은 true 이므로 ? 물음표 바로 뒤에 값이 반환(그려짐)됨 //useEffect로 인해 데이터가 준비되고, ready 값이 변경되면 : 콜론 뒤의 값이 반환(그려짐) //useEffect는 화면이 한번 그려지고 난 다음에 실행됨 근데 지금은 useState로 화면을 그리는데 useState가 비어서 오류남 //따라서 아래와 같은 삼항연산자를 이용하여 //우선 로딩화면을 한번 그린 다음에 useEffect를 이용하여 데이터를 불러오는것 return ready ? <Loading/> : ( /* return 구문 안에서는 {슬래시 + * 방식으로 주석 */ <ScrollView style={styles.container}> <Text style={styles.title}>나만의 꿀팁</Text> <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text> <Image style={styles.mainImage} source={main}/> <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}> <TouchableOpacity style={styles.middleButton01}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton02}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton03}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton04}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity> </ScrollView> <View style={styles.cardContainer}> {/* 하나의 카드 영역을 나타내는 View */} { tip.map((content,i)=>{ return (<Card content={content} key={i}/>) }) } </View> </ScrollView> ); } const styles = StyleSheet.create({ container: { //앱의 배경 색 backgroundColor: '#fff', }, title: { //폰트 사이즈 fontSize: 20, //폰트 두께 fontWeight: '700', //위 공간으로 부터 이격 marginTop:50, //왼쪽 공간으로 부터 이격 marginLeft:20 }, weather:{ alignSelf:"flex-end", paddingRight:20 }, mainImage: { //컨텐츠의 넓이 값 width:'90%', //컨텐츠의 높이 값 height:200, //컨텐츠의 모서리 구부리기 borderRadius:10, marginTop:20, //컨텐츠 자체가 앱에서 어떤 곳에 위치시킬지 결정(정렬기능) //각 속성의 값들은 공식문서에 고대로~ 나와 있음 alignSelf:"center" }, middleContainer:{ marginTop:20, marginLeft:10, height:60 }, middleButton01: { width:100, height:50, padding:15, backgroundColor:"#fdc453", borderColor:"deeppink", borderRadius:15, margin:7 }, middleButton02: { width:100, height:50, padding:15, backgroundColor:"#fe8d6f", borderRadius:15, margin:7 }, middleButton03: { width:100, height:50, padding:15, backgroundColor:"#9adbc5", borderRadius:15, margin:7 }, middleButtonText: { color:"#fff", fontWeight:"700", //텍스트의 현재 위치에서의 정렬 textAlign:"center" }, middleButton04: { width:100, height:50, padding:15, backgroundColor:"#f886a8", borderRadius:15, margin:7 }, cardContainer: { marginTop:10, marginLeft:10 }, }); |
-----------------------------------------------------------------------------------------------------------------------------------
3-8-------------------------------------------------------------------------------------------------------------------------------
const category = (cate) => { if(cate == "전체보기"){ //넘어온 cate문자열이 '전체보기'라면 setCateState에 state즉 원본 그대로의 data를 넣는다. setCateState(state) }else{ //filter를 사용해 state에서 cate와 같은 category를 가진 애만 넣는다. setCateState(state.filter((d)=>{ return d.category == cate })) } } . . . return ready ? <Loading/> : ( /* 각 TouchableOpacity터치시 onPress함수 실행, onPress내부의 category함수 호출, 상단의 category함수 실행 */ <ScrollView style={styles.container}> <Text style={styles.title}>나만의 꿀팁</Text> <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text> <Image style={styles.mainImage} source={main}/> <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}> <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('꿀팁 찜')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity> </ScrollView> <View style={styles.cardContainer}> {/* 하나의 카드 영역을 나타내는 View */} { cateState.map((content,i)=>{ return (<Card content={content} key={i}/>) }) } </View> </ScrollView> ); } |
setCateState(state.filter((d)=>{ return d.category == cate } //filter를 사용하면 state내부의 요소 하나를 d라고 두게되고 반복문을 돌림 //return 에 true인것만 포함하여 setCateState에 리스트 형태로 넣게됨 |
-----------------------------------------------------------------------------------------------------------------------------------
3-9-------------------------------------------------------------------------------------------------------------------------------
상태바 관리하기
https://docs.expo.io/versions/v38.0.0/
API Reference - Expo Documentation
Expo is an open-source platform for making universal native apps for Android, iOS, and the web with JavaScript and React.
docs.expo.io
위 링크에서 expo에서 제공하는 여러 기능 api 를 확인하능함
상태바 관리 api를 다운받아야 됨
expo install expo-status-bar입력
import { StatusBar } from 'expo-status-bar'; . . . <StatusBar style="dark" /> |
-----------------------------------------------------------------------------------------------------------------------------------
3-10,11--------------------------------------------------------------------------------------------------------------------------
앱 페이지 이동하기-> 네비게이션
얘도 expo 의 라이브러리
설치(여러 종류의 네비게이터들을 사용하기 위해 기본적으로 설치하는 api)
1. yarn add @react-navigation/native
2. 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라고한다
스택 네비게이터 설치
yarn add @react-navigation/stack
적용
-우선 navigation폴더를 만든다
그리고 폴더안에 Stack_navigator.js를 만든다

Stack_navigator.js |
import React from 'react'; //설치한 스택 네비게이션 라이브러리를 가져옵니다 import { createStackNavigator } from '@react-navigation/stack'; //페이지로 만든 컴포넌트들을 불러옵니다 import DetailPage from '../pages/Detail_page'; import MainPage from '../pages/Main_page'; //스택 네비게이션 라이브러리가 제공해주는 여러 기능이 담겨있는 객체를 사용합니다 //그래서 이렇게 항상 상단에 선언하고 시작하는게 규칙입니다! const Stack = createStackNavigator(); const Stack_navigator = () =>{ 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 Stack_navigator; //export 하여서 Stack_navigator함수를 외부에서 사용 가능하게 함 |
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/Stack_navigator' export default function App() { console.disableYellowBox = true; return ( <NavigationContainer> <StatusBar style="black" /> <StackNavigator/> </NavigationContainer>); } |
App.js에서 이 네비게이터를 불러와 사용함
********주의***********

각 api설치시 반드시 해당 프로젝트 파일 내부(App.js가 있는 파일)로 cd한 다음에 설치해야됨
(api위치 때문인것같음..)
-----------------------------------------------------------------------------------------------------------------------------------
3-12------------------------------------------------------------------------------------------------------------------------------
네비게이터 헤더 조정하기
StackNavigator.js |
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: "white", borderBottomColor: "white", shadowColor: "white", height:100 }, //헤더의 텍스트를 왼쪾에 둘지 가운데에 둘지를 결정 headerTitleAlign:'left', headerTintColor: "#000", headerBackTitleVisible: false }} > {/* 컴포넌트를 페이지로 만들어주는 엘리먼트에 끼워 넣습니다. 이 자체로 이제 페이지 기능을 합니다*/} <Stack.Screen name="MainPage" component={MainPage}/> <Stack.Screen name="DetailPage" component={DetailPage}/> </Stack.Navigator> ) } export default StackNavigator; |
screenOptions에서 헤더의 색이나 크기를 조정할수있음.
-----------------------------------------------------------------------------------------------------------------------------------
3-13------------------------------------------------------------------------------------------------------------------------------
메인페이지에서 네비게이터 헤더 설정하기
MainPage.js |
import React,{useState,useEffect} from 'react'; import main from '../assets/main.png'; import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native'; import data from '../data.json'; import Card from '../components/Card'; import Loading from '../components/Loading'; import { StatusBar } from 'expo-status-bar'; export default function MainPage({navigation,route}) {//좌측과 같이 MainPage인자로 navigation, route를 넣음 console.disableYellowBox = true; //return 구문 밖에서는 슬래시 두개 방식으로 주석 //기존 꿀팁을 저장하고 있을 상태 const [state,setState] = useState([]) //카테고리에 따라 다른 꿀팁을 그때그때 저장관리할 상태 const [cateState,setCateState] = useState([]) //컴포넌트에 상태를 여러개 만들어도 됨 //관리할 상태이름과 함수는 자유자재로 정의할 수 있음 //초기 상태값으로 리스트, 참거짓형, 딕셔너리, 숫자, 문자 등등 다양하게 들어갈 수 있음. const [ready,setReady] = useState(true) useEffect(()=>{ //뒤의 1000 숫자는 1초를 뜻함 //1초 뒤에 실행되는 코드들이 담겨 있는 함수 setTimeout(()=>{ //헤더의 타이틀 변경 navigation.setOptions({ title:'나만의 꿀팁'//상단에서 받은 navigation으로 setOptions하여 페이지별 헤더 이름 변경가능 }) //꿀팁 데이터로 모두 초기화 준비 let tip = data.tip; setState(tip) setCateState(tip) setReady(false) },1000) },[]) . . . <ScrollView style={styles.container}> <StatusBar style="black" /> {/* <Text style={styles.title}>나만의 꿀팁</Text> */} <Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text> <Image style={styles.mainImage} source={main}/> <ScrollView style={styles.middleContainer} horizontal indicatorStyle={"white"}> <TouchableOpacity style={styles.middleButtonAll} onPress={()=>{category('전체보기')}}><Text style={styles.middleButtonTextAll}>전체보기</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton01} onPress={()=>{category('생활')}}><Text style={styles.middleButtonText}>생활</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton02} onPress={()=>{category('재테크')}}><Text style={styles.middleButtonText}>재테크</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton03} onPress={()=>{category('반려견')}}><Text style={styles.middleButtonText}>반려견</Text></TouchableOpacity> <TouchableOpacity style={styles.middleButton04} onPress={()=>{category('꿀팁 찜')}}><Text style={styles.middleButtonText}>꿀팁 찜</Text></TouchableOpacity> </ScrollView> <View style={styles.cardContainer}> {/* 하나의 카드 영역을 나타내는 View */} { cateState.map((content,i)=>{ return (<Card content={content} key={i} navigation={navigation}/>) {/*위와 같이 navigation을 Card로 전달하여 사용*/} }) } </View> </ScrollView> |
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로 감싸서 MainPage.js 로 return 한다 그러면 TouchableOpacity가 됨 화면에 뜨는게 <TouchableOpacity style={styles.card} onPress={()=>{navigation.navigate('DetailPage')}}> //touchable opacity에 onpress해놓고 navigation.navigate('페이지이름')하면 그 페이지로감 <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> ) } const styles = StyleSheet.create({ card:{ flex:1, flexDirection:"row", margin:10, borderBottomWidth:0.5, borderBottomColor:"#eee", paddingBottom:10 }, cardImage: { flex:1, width:100, height:100, borderRadius:10, }, cardText: { flex:2, flexDirection:"column", marginLeft:10, }, cardTitle: { fontSize:20, fontWeight:"700" }, cardDesc: { fontSize:15 }, cardDate: { fontSize:10, color:"#A6A6A6", } }); |
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}) {//Card.js에서 navigation, route를 전달받음 //초기 컴포넌트의 상태값을 설정 //state, setState 뿐 아니라 이름을 마음대로 지정할 수 있음! const [tip, setTip] = useState({ "idx":9, "category":"재테크", "title":"렌탈 서비스 금액 비교해보기", "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Frental.png?alt=media&token=97a55844-f077-4aeb-8402-e0a27221570b", "desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ", "date":"2020.09.09" })//얘는 뭐냐면 아까는 useState에 데이터가 없었기때문에 로딩화면 만든거고 //얘는 걍 처음부터 더미 데이터를 useState에 미리 넣어놓고 그 다음에 알맞은 값을 넣는것 //그래서 잘~ 보면 알맞은 데이터 뜨기전에 보라색 이미지가 슬쩍 보임 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 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-14------------------------------------------------------------------------------------------------------------------------------
공유기능 넣기->리액트에서 Share를 제공한다
DetailPage.js |
import React,{useState,useEffect} from 'react'; import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert,Share } from 'react-native'; //Share를 import export default function DetailPage({navigation,route}) { const [tip, setTip] = useState({ "idx":9, "category":"재테크", "title":"렌탈 서비스 금액 비교해보기", "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Frental.png?alt=media&token=97a55844-f077-4aeb-8402-e0a27221570b", "desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ", "date":"2020.09.09" }) useEffect(()=>{ console.log(route) navigation.setOptions({ title:route.params.title, headerStyle: { backgroundColor: '#000', shadowColor: "#000", }, headerTintColor: "#fff", }) setTip(route.params) },[]) const popup = () => { Alert.alert("팝업!!") } const share = () => { Share.share({ message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`, }); } 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> <View style={styles.buttonGroup}> <TouchableOpacity style={styles.button} onPress={()=>popup()}><Text style={styles.buttonText}>팁 찜하기</Text></TouchableOpacity> <TouchableOpacity style={styles.button} onPress={()=>share()}><Text style={styles.buttonText}>팁 공유하기</Text></TouchableOpacity> </View> </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" }, buttonGroup: { flexDirection:"row", }, button:{ width:100, marginTop:20, marginRight:10, marginLeft:10, padding:10, borderWidth:1, borderColor:'deeppink', borderRadius:7 }, buttonText:{ color:'#fff', textAlign:'center' } }) |
share함수내부의 message:val val에 공유할 문자열을 넣는다.
-----------------------------------------------------------------------------------------------------------------------------------
3-15------------------------------------------------------------------------------------------------------------------------------
외부링크 달기
-expo linking을 설치한다
expo install expo-linking
-import * as Linking from 'expo-linking'; 으로 설치한것을 불러옴
DetailPage.js |
import React,{useState,useEffect} from 'react'; import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert,Share } from 'react-native'; import * as Linking from 'expo-linking'; export default function DetailPage({navigation,route}) { const [tip, setTip] = useState({ "idx":9, "category":"재테크", "title":"렌탈 서비스 금액 비교해보기", "image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Frental.png?alt=media&token=97a55844-f077-4aeb-8402-e0a27221570b", "desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ", "date":"2020.09.09" }) useEffect(()=>{ console.log(route) navigation.setOptions({ title:route.params.title, headerStyle: { backgroundColor: '#000', shadowColor: "#000", }, headerTintColor: "#fff", }) setTip(route.params) },[]) const popup = () => { Alert.alert("팝업!!") } const share = () => { Share.share({ message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`, }); } const link = () => { Linking.openURL("https://spartacodingclub.kr") }//link함수에 Linking.openURL해서 열 주소를 넣음 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> <View style={styles.buttonGroup}> <TouchableOpacity style={styles.button} onPress={()=>popup()}><Text style={styles.buttonText}>팁 찜하기</Text></TouchableOpacity> <TouchableOpacity style={styles.button} onPress={()=>share()}><Text style={styles.buttonText}>팁 공유하기</Text></TouchableOpacity> <TouchableOpacity style={styles.button} onPress={()=>link()}><Text style={styles.buttonText}>외부 링크</Text></TouchableOpacity> </View> </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" }, buttonGroup: { flexDirection:"row", }, button:{ width:90, marginTop:20, marginRight:10, marginLeft:10, padding:10, borderWidth:1, borderColor:'deeppink', borderRadius:7 }, buttonText:{ color:'#fff', textAlign:'center' } }) |