React-native 를 본격적으로 배우면서 만들어본
MovieApp 의 다양한 기능들을 정리했습니다.
시작하기에 앞서 모든 파일을 typescript 로 변경하고 싶다면
이 사이트에 들어가서 Adding TypeScript to an Existing Project 챕터의 4번째 part 까지 똑같이 따라 하시면 타입스크립트 적용
( https://reactnative.dev/docs/typescript )
react-native-web-swiper
react-native 에서는 swiper 기능을 지원해 줍니다.
지원해 주는 코드도 여러개가 있지만 ios, android 를 지원해 주는 react-native-web-swiper 을 사용하는 것을 추천합니다.
설치
npm i react-native-web-swiper
import Swiper from 'react-native-web-swiper';
import styled from 'styled-components/native';
const Movie = () => {
return (
<Container >
<Swiper
loop
timeout={2}
controlsEnabled = {false}
containerStyle={{width: "100%", height: 300 }}
>
<View style={{backgroundColor: "red"}}></View>
<View style={{backgroundColor: "blue"}}></View>
<View style={{backgroundColor: "red"}}></View>
<View style={{backgroundColor: "blue"}}></View>
</Swiper>
</Container>
)
}
const Container = styled.ScrollView`
flex: 1;
background-color: ${props => props.theme.mainBgColor};
`
const View = styled.View`
flex: 1;
`
export default Movie
react-native-web-swiper 에서 Swiper 을 꺼낸 다음 사용하시면 됩니다.
여기서 loop, timeout, controlsEnabled 등의 옵션이 있는데 react-native-web-swiper 에서 지원해 주는 options 입니다.
https://github.com/reactrondev/react-native-web-swiper
Dimensions
Dimensions 는 react-native 에서 기본 제공해 주는 기능으로 앱 사이즈에 맞게 자동으로 넓이, 높이를 계산해 줍니다.
import { Dimensions } from "react-native";
const { height } = Dimensions.get("window")
const Home = () => {
return (
<View style={{ width: "100%", height: height }} ></View>
)
}
export default Home
이렇게 설정을 해주면 height 는 핸드폰 크기게 맞게 자동적으로 전체 넓이로 맞추어 줍니다.
ActivityIndicator
간단하게 loading 하는 이미지를 보여주는 기능입니다.
react-native 에서 손쉽게 지원하기 때문에 react-native 에서 불러서 사용하시면 됩니다.
import { ActivityIndicator } from 'react-native';
return (
<ActivityIndicator/>
)
absoluteFill
부모 컴포넌트의 크기와 위치를 모두 채우는 기능입니다.
주로 모달 창이나 전체 화면 배경과 같이 부모 요소를 꽉 채우는 컴포넌트를 만들 때 유용합니다.
react-native 에서 제공해 주는 기능으로 StyleSheet 에서 꺼내서 사용하면 됩니다.
import { StyleSheet } from "react-native";
<View style={ StyleSheet.absoluteFill } > </View>
Swiper 의 IOS 버그
위에서 배웠던 react-native-web-swiper 은 IOS 에 경우 해당 Swiper 안에 components 들을 클릭한 상태에서 드래그를 위아래로 한다면 이상하게 상하좌우로 마음대로 이동하는 모습을 볼 수 있습니다. android 는 해당이 되지 않지만 IOS 는 보기에 불편하기 때문에
react-native-swiper 을 사용 할 수 있습니다.
설치
npm i react-native-swiper@next
import Swiper from "react-native-swiper";
<Swiper
horizontal
loop
autoplay
autoplayTimeout={3.5}
showsButtons={false}
showsPagination={false}
containerStyle={{width: "100%", height: SCREEN_HEIGHT / 4}}
>
// ... 다양한 component
</Swiper>
react-native-swiper 의 경우에도 다양한 options 들을 지원하니 구글링 하시면 쉽게 찾아볼 수 있습니다.
refresh
refresh 는 react native 에서 제공하는 새로고침 시 나타나는 화면 기능입니다.
아이폰을 기준으로 만약 화면을 최상단에서 손가락으로 꾹 누르고
아래로 내리게 되면 새로고침이 되는 기능이라고 생각하시면 됩니다.
이때 refresh 는 ScrollView Tag 안에서 사용됩니다.
refresh 기능을 사용할 때 밑에 코드처럼 사용해 주면 됩니다.
// 생략
const [refreshing, setRefreshing] = useState(false);
const onRefresh = async () => {
setRefreshing(true);
await getData();
setRefreshing(false);
}
return (
<Container refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh}/> }>
//....
)
FlatList
FlatList는 효율적으로 대량의 데이터 목록을 표시하는 컴포넌트입니다.
반면에 ScrollView는 모든 자식 컴포넌트를 한 번에 렌더링하여 메모리 사용량과 성능 문제를 일으킬 수 있습니다.
즉 scrollView 를 사용하면 우리의 어플리케이션의 성능을 느리게 할 수 있습니다.
공식 문서에서도 나와있지만 scrollView 는 모든 자식 컴포넌트를 한번에 render 합니다.
즉 모바일 화면에서 아직 보이지 않는 component 들이 미리 렌더링이 완료된다는 뜻입니다.
scrollView 는 그래서 component 가 그리 많지 않는 환경에서 쓰면 좋습니다.
따라서 등장한 것이 FlatList 입니다.
FlatList 는 요소들을 "게으르게" render 해줍니다.
즉 component 가 화면에 나타나기 직전에야 component 를 render 해줍니다.
이러한 기능을 "lazy render" 라고 합니다.
scrollView 를 사용했을 경우 아래 코드처럼 만들면 됩니다.
<TrendingScroll>
{trending.map(movie => (
<VMedia
key={movie.id}
posterPath={movie.poster_path}
originalTitle={movie.original_title}
voteAverage={movie.vote_average}
/>
))}
</TrendingScroll>
하지만 FlatList 를 위에 코드에서 사용하게 된다면 아래처럼 변경되게 됩니다.
🔻🔻🔻 이렇게 변경됩니다.
<FlatList
data={trending}
renderItem={({item}) => (
<VMedia
posterPath={item.poster_path}
originalTitle={item.original_title}
voteAverage={item.vote_average}
/>
)}
/>
코드를 읽어보면 FlatList 의 prop 으로 data, renderItem 이라는 것이 보이실 겁니다.
FlatList 는 두개의 필수 prop 을 가지고 있어야 합니다. 하나는 데이터입니다. 즉 render 을 할 대상이죠.
두번째 필수 prop 은 renderItem 입니다. renderItem 은 함수이며 인자를 하나 받는데
첫번째 인자는 객체이며 첫번째 속성은 item(FlatList 가 render 하려고 하는 대상) 입니다.
해당 item 을 통해서 원하는 component 를 customize 할 수 있습니다.
즉 배열로 된 ( [ { name: "chan", age: "26" }, { name: "chan", age: "26" } .....] )
trending Data 를 하나하나 꺼낸 것이 item ( { name: "chan", age: "26" } )입니다.
FlatList 의 기능 중 하나는 요소들 사이에 특정 component 를 만들어 넣을 수 있습니다.
만약 어떤 요소 [1,2,3,4,5,6] 이 있고 이것들을 FlatList 로 정렬하다가 디자이너 분께서
"저 숫자 사이에 이미지를 추가하고 싶어요." 라고 하면 하나하나 다시 코드를 바꿔야하는 불편함이 존재합니다.
하지만 FlatList 의 ItemSeparatorComonent 기능을 이용하면 손쉽게 해결이 가능합니다.
<FlatList
horizontal // <-- 세로 방향으로 바꾸기
showsHorizontalScrollIndicator={false} // <-- 스크롤 바 없애기
contentContainerStyle={{paddingHorizontal: 20}} // <-- 전체 container 의 스타일
ItemSeparatorComponent={() =><View style={{width: 20}}/>} // <-- 요소 중간에 어떤 component 넣기
keyExtractor={item => item.id} // <-- 개별 요소의 key 값
data={trending}
renderItem={({item}) => (
<VMedia
posterPath={item.poster_path}
originalTitle={item.original_title}
voteAverage={item.vote_average}
/>
)}
/>
또한 keyExtractor 를 사용한 이유는 FlatList 는 일반적인 map 메서드로 key 값을 넣는 것과 달리
key 값을 각 요소에 어떤 key 를 넣어줘야 하는지 FlatList 에게 알려주는 함수를 만들어야 합니다
FlatList 에 ScrollView 는 쓰지 않아요
만약 FlatList 안에 scrollView 를 넣어주면 어떻게 될까요?? 작동은 하긴 하지만 react-native 에서는 권장하지 않습니다.
FlatList 자체가 스크롤 가능한 컴포넌트이기 때문에 FlatList 안에 ScrollView를 중첩해서 사용하는 것은 권장되지 않는 것이죠.
당연하게도 FlatList 의 취지는 Component 가 화면에 보여질 때 render 하는 기능을 제공해 주는 것이지만 FlatList 안에
ScrollView 를 쓰게 된다면 해당 기능의 장점이 사라지기 때문입니다.
어? 그럼 FlatList 는 rederItem 으로 하나의 컴포넌트만 넣을 수 있는데
데이터가 다른 여러개의 Component 를 넣고 싶으면 어떻게 해야 하나요??
그 때 FlatList 에서 제공해주는 기능은 ListHeaderComponent 라는 기능입니다.
이 기능은 FlatList 에서 renderItem 으로 보여주는 요소 위에 어떤 Component 들을 보여주고 싶을 때 사용하는 기능입니다.
이렇게 ListHeaderComponent 를 적용해 주면 renderItem 위에 Component 들을 넣어 줄 수 있습니다.
web-browser
이 기능은 link 로 다른 정보로 이동할 때 다른 새로운 어플이나 사이트로 이동하는 것이 아니라 내 어플에서 해당
정보를 확인할 수 있게 해주는 기능입니다. 무슨 말인지 잘 이해가 안될 수 있으니 아래 그림을 참고하시면 됩니다.
설치
npx expo install expo-web-browser
// 만약 ios 사용중이라면 web-browser 설치 한 후에
npx pod-install ios
설치가 끝났으면 사용하고 싶은 곳에 비동기 방식으로 사용하시면 됩니다.
import * as WebBrowser from "expo-web-browser";
const openYTLink = async (videoID : string) => {
const baseUrl = `https://m.youtube.com/watch?v=${videoID}`;
await WebBrowser.openBrowserAsync(baseUrl);
}
또는 react-native 에 자체적으로 가지고 있는 Linking 을 사용해서 새로운 정보 사이트로 이동해 줄 수 있습니다.
이 방식은 기존 어플에서 사이트를 켜주는 것이 아니라 아예 어플을 나가서 새로운 사이트에 접속합니다.
import { Linking } from "react-native";
const openYTLink = async (videoID : string) => {
const baseUrl = `https://m.youtube.com/watch?v=${videoID}`;
await Linking.openURL(baseUrl);
}
Share
만약 특정 데이터를 여러 사람에게 공유하고 싶다면 어떻게 해야 할까요??
그때는 React-native 에서 제공해주는 Share 기능을 사용하면 됩니다.
Share 을 사용할 때도 비동기적으로 사용하셔야 합니다.
밑에는 사용하는 예시 코드 입니다.
import {Share} from "react-native";
const shareMedia = async () => {
await Share.share({
message: " 공유하고 싶은 데이터의 설명입니다.",
title: " 공유 데이터 "
})
}
'React-native' 카테고리의 다른 글
React-native 에서 firebase 적용하기 (0) | 2024.06.21 |
---|---|
React-native - Animation (1) | 2024.06.13 |
React-native (0) | 2024.05.23 |