리액트 컴포넌트, 속성, 상태
리액트 기초지식
- 컴포넌트(Component) : 정해진 요소를 사용하여 만든 화면의 일부분
- 상태(State) : 컴포넌트에서 데이터를 유지하고 관리하기 위한 방법 = 데이터
- 속성(Props) : 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 방식 = 데이터 전달
- useEffect : 화면에 컴포넌트가 그려지면 처음 실행해야 하는 함수들을 모아두는 곳
- Component에 있는 Props가 데이터를 전달 → Component 안의 State가 데이터를 관리
컴포넌트(Component)
- UI 요소, 화면의 모든 부분
- Card.js
//비구조 할당 방식으로 넘긴 속성 데이터를 꺼내 사용함
export default function Card({content}) {
return (<View style={styles.card}>
<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>
</View>)
}
- 비구조 할당 방식 이용
- MainPage.js
import Card from '../components/Card';
...
<View style={styles.cardContainer}>
{/* 하나의 카드 영역을 나타내는 View */}
{
tip.map((content,i)=>{
return (<Card content={content} key={i}/>)
})
}
</View>
- MainPage.js에서 Card.js로 content라는 데이터를 넘겼다.
속성(Props)
- 컴포넌트에 데이터를 전달하는 것
- key와 value의 형태 (ex. content={content})
- 컴포넌트에 대해
map
으로 반복문 → 반드시 인덱스(i)를key={i}
로 속성 전달
상태(useState)와 useEffect
- 컴포넌트마다 보유, 관리하는 데이터를
상태
라고 한다.
- 리액트에서 상태(state) →
useState
로 생성,setState
로 변경 가능
useState
- 리액트에서 화면은 데이터에 따라 변경되고, 상태(state)로 관리되는 데이터가 변경되면 화면이 바뀐다.
- UI = component(state)
useEffect
- 화면이 로딩되고 가장 먼저 실행되는 함수
useEffect(()=>{
화면이 그려지고 나서 가장 먼저 실행돼야 할 코드
},[])
- 데이터를 준비(데이터를 받고 상태(state)에 반영)할 때 사용
- 화면이 그려진다 → useEffect가 데이터를 준비 → 상태 데이터가 업데이트 되었으니 다시 화면이 그려진다
const [state, setState] = useState([])
useEffect(()=>{
setState(data)
},[])
- state : 컴포넌트에서 관리될 상태 데이터를 담고 있는 변수
- setState : state를 변경시킬 때 사용해야하는 함수
- useState() 안에 전달되는 것 → state 초기값
- useEffect 함수로 data.json에서 가져온 데이터를 state에 담음
로딩 화면
- useEffect는 화면이 그려지고 나서 실행되는데, 현재는 화면을 그릴 때 이용할 state에 값이 설정되어 있지 않은 상태임
- 따라서 로딩 화면을 먼저 그린 후 → useEffect를 통해 state를 설정하고 나서 → 메인 화면을 그려야 오류가 나지 않음
- Loading.js 파일 생성 후 MainPage.js를 다음과 같이 수정
import Loading from '../components/Loading';
const [state,setState] = useState([])
const [ready,setReady] = useState(true) //초기 ready : True
useEffect(()=>{
setTimeout(()=>{
setState(data)
setReady(false)
},1000) //1000 = 1초
},[])
- 상태는 여러개 만들어도 된다.
- setTimeout으로 1초 뒤에 상태 관리에 들어가게 함
return ready ? <Loading/> : (
<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}>
{
tip.map((content,i)=>{
return (<Card content={content} key={i}/>)
})
}
</View>
</ScrollView>
);
- 삼항연산자를 이용해서 ready가
true
이면 로딩 화면을,false
이면 메인 화면을 그린다.
- 실행 순서
- 초기 ready 상태는
true
여서 로딩 화면을 먼저 그림
- useEffect가 실행돼서 1초 뒤에 state 값을 설정, ready를
false
로 변경
- ready 상태가 변경되었으니 자동으로
retrun ready ? ...
가 실행됨
false
이므로 메인 화면이 그려짐
- 초기 ready 상태는
카테고리 기능
MainPage.js
const [state,setState] = useState([]) //전체 리스트
const [cateState,setCateState] = useState([]) //카테고리 선택에 따른 리스트
const [ready,setReady] = useState(true)
useEffect(()=>{
setTimeout(()=>{
let tip = data.tip;
setState(tip)
setCateState(tip) //처음 로딩 시 전체 리스트로 초기화
setReady(false)
},1000)
},[])
- 선택한 카테고리에 따라 보여줄 리스트를 저장하는 cateState
- useEffect에서 cateState를 tip (전체 데이터) 으로 초기화
<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>
- 카테고리 버튼마다 onPress 함수를 설정함
- category 함수에 카테고리 이름을 넘겨주도록 함
const category = (cate) => {
if(cate == "전체보기"){
//전체보기면 원래 꿀팁 데이터를 담고 있는 상태값으로 다시 초기화
setCateState(state)
}else{ //전체(state)에서 선택한 카테고리 데이터만 추출
setCateState(state.filter((d)=>{
return d.category == cate //true일때 cateSate에 넣는다
}))
}
}
- category 함수에는 cate(카테고리 이름) 파라미터가 있음
- 전체보기를 클릭했다면 cateState를 전체 데이터(state)로 변경
- 그 외 카테고리 버튼을 클릭했다면 전체 데이터(state) 중 해당 카테고리에 속하는 데이터만 cateState에 저장 (
filter
함수 이용)
스택네비게이터
네비게이션
- 컴포넌트들을 페이지화 시켜서 해당 페이지끼리 이동을 가능하게 하는 라이브러리
- 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
: 책갈피 (모든 페이지를 등록시킬 곳)
설치
yarn add @react-navigation/stack
적용하기
- StackNavigator.js
import { createStackNavigator } from '@react-navigation/stack';
//페이지로 만들 컴포넌트 불러오기
import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';
const Stack = createStackNavigator();
const StackNavigator = () =>{
return (
<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;
- App.js
import React from 'react';
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>);
}
- 앱의 가장 최상위 컴포넌트인 App.js에 네비게이션 기능을 달아준 것
- NavigationContainer 태그로 StatusBar(상태바)과 StackNavigator(직접 만든 스택네비게이션)을 감싼다.
navigation.setOptions({
title:'나만의 꿀팁'
})
navigation.navigate("DetailPage")
navigation.navigate("DetailPage",{
title: title
})
const { title} = route.params; //비구조 할당방식
navigation
- setOptions : 제목, 헤더 옵션 스타일 등 바꿀 수 있음
- navigate : 해당 페이지로 이동하는 함수 (StackNavigator.js의 Stack.screen name 속성), 두번째 매개변수로 딕셔너리 데이터 전달
route
: navigate로 인해 전달받은 데이터를 받는 딕셔너리
공유하기 기능
- React Native 자체에서 제공하는 기능이다.
import { Share } from "react-native";
export default function DetailPage({navigation,route}) {
...
const share = () => {
Share.share({
message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
});
}
return (
<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>
)
}
- share 함수를 이용해 공유할 때 전달할 제목, 설명, 이미지 등을 설정할 수 있음
외부 링크 클릭 이벤트
도구 설치
expo install expo-linking
적용하기
import * as Linking from 'expo-linking';
const link = () => {
Linking.openURL("https://spartacodingclub.kr")
}
<TouchableOpacity style={styles.button} onPress={()=>link()}><Text style={styles.buttonText}>외부 링크</Text></TouchableOpacity>
리액트를 기반으로 하는 리액트 네이티브를 공부하고 있기 때문에
리액트의 기초 지식인 컴포넌트/속성/상태에 대해 공부했다.
상태의 개념이 처음 접했을 때 헷갈렸는데, 상태의 변화가 일어날 때 화면을 새로 그린다는 것에 유의하자.
스택네비게이터를 이용해 여러 페이지간의 이동을 구현하는 방법을 알게 되어 좀더 앱다운 앱을 만들 수 있게 되었다.
그 외 공유하기 및 외부 링크 클릭 이벤트를 구현하는 방법을 익혀서 추후에 앱을 출시하게 된다면 유용하게 사용할 수 있을 것 같다!
스택네비게이션의 이용을 여러 번 복습해서 익숙해질때까지 공부해야겠다.
'[스파르타코딩클럽] > 앱개발 종합반' 카테고리의 다른 글
스파르타코딩클럽 앱개발 종합반 완주 후기 (0) | 2021.07.15 |
---|---|
앱개발 종합반 5주차 정리 (구글 애드몹 설정, 배포하기) (0) | 2021.07.10 |
앱개발 종합반 4주차 정리 (날씨 서버 외부 API, 파이어베이스 사용하기) (0) | 2021.06.24 |
앱개발 종합반 2주차 정리 (Expo 설치, React Native 태그, Styles, Flex) (0) | 2021.06.15 |
앱개발 종합반 1주차 정리 (자바스크립트 기초) (0) | 2021.06.12 |
Uploaded by Notion2Tistory v1.1.0