[TIL] 내일배움캠프 React 과정 2023.01.04

Today I Learned

  • React Native 심화 강의 수강

 


LinearGradient 사용하기

<LinearGradient colors={["transparent", "black"]} style={StyleSheet.absoluteFill} />

배경 이미지에 그라디언트 효과를 줄 때 LinearGradient를 사용한다. colors라는 porp을 넘겨서 배열 형태로 원하는 그라디언트 효과를 구현할 수 있다. ["transparent", "black"]는 투명에서 검은색으로 그라디언트 효과를 주고 싶다는 것을 의미한다.

 

 

flex-end 속성

  • flex-end: 아이템들을 끝으로 정렬한다. flex-direction이 row(가로 배치)일 때는 아래, column(세로 배치)일 때는 오른쪽에 위치한다.
  • 출처 https://studiomeal.com/archives/197

 

StyleSheet.absoluteFill

// 동일한 코드
<View style={{position: 'absolute', left: 0, right: 0, top: 0, bottom: 0}}>
<View style={StyleSheet.absoluteFill}>

배경이미지 적용 시 자주 사용되는 패턴 코드 간소화

 

 

 

기기의 실제 너비와 높이 구하기

import { Dimensions } from "react-native";

export const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } =
  Dimensions.get("window");

Dimensions API를 통해서 실제 스크린너비와 높이값을 구할 수 있다.

 

height: ${SCREEN_HEIGHT / 3 + "px"};

사용 예시

 

 

react-native-swiper 사용하기

<Swiper height="100%" showsPagination={false} sutoplay loop>
    <BestMovieContainer>
		...생략...
    </BestMovieContainer>
</Swiper>

사용하고자 하는 요소를 <Swiper>로 감싸고 속성을 설정한다. height는 기본적으로 화면 모두를 차지(flex: 1)하기 때문에 필수로 설정해줘야 한다.

참고 https://github.com/leecade/react-native-swiper

 

 

로딩 중 화면 표시하기

const [isLoading, setIsLoading] = useState(true);

useState로 isLoading을 만들어서 데이터를 가져오는데 성공하면 setIsLoading(false)로 변경한다.

 

if (isLoading) {
        return (
            <Loader>
                <ActivityIndicator size="large"/>
            </Loader>
        );
    };

if문으로 isLoading이 true일 때 로딩 애니메이션 표현하는 <ActivityIndicator> 컴포넌트를 이용해서 화면에 띄워준다.

 

 

영화정보 API 가져오기

const getNowPlaying = async() => {
    const { results } = await fetch(
        `${BASE_URL}/now_playing?api_key=${API_KEY}&language=en-US&page=1`
    ).then((res) => res.json());
    setNowPlaying(results)
    setIsLoading(false);
};

fetch를 이용해서 API의 데이터를 가져온 후에 state에 담는다.

API 링크 https://www.themoviedb.org/

 

 

Promise.all

const getData = async () => {
    await Promise.all([getNowPlaying(), getTopRated(), getUpcoming()]);
    setIsLoading(false);
};
  • function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환한다. 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록 한다.
  • 출처 https://ko.javascript.info/async-await

 

 

RefreshControl-스크롤로 새로고침 처리하기

const [isRefreshing, setIsRefreshing] = useState(false);

const onRefresh = async () => {
    setIsRefreshing(true);
    await getData();
    setIsRefreshing(false);
};

<ScrollView refreshControl={
    <RefreshControl refreshing={isRefreshing} onRefresh={onRefresh} />
}>

최상위 <ScrollView> 컴포넌트에 <RefreshControl>을 넣고, isRefreshing state와 onRefresh라는 함수를 이용해서 스크롤을 내렸을 때 새로고침 처리를 할 수 있다.

  • refreshing: Whether the view should be indicating an active refresh. (type: boolean)
  • onRefresh: Called when the view starts refreshing. (type: function)

공식 문서 https://reactnative.dev/docs/refreshcontrol#onrefresh

 

 <FlatList
  refreshing={isRefreshing}
  onRefresh={onRefresh}
/>

+) FlatList를 사용할 때는 <RefreshControl>을 따로 사용하지 않아도 된다.

  • onRefresh: If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the refreshing prop correctly.

 

FlatList란?

<FlatList 
    horizontal
    contentContainerStyle={{ paddingHorizontal: 10 }}
    showsHorizontalScrollIndicator={false}
    data={topRated} //필수 요소
    renderItem={({ item }) => <TopRatedCard movie={item} />} //필수 요소
    keyExtractor={(item) => item.id}
    // ItemSeparatorComponent={ <View style={{ width: 10 }} /> }
/>
  • ScrollView: 모든 리스트들을 한번에 렌더링 해야 해서 리스트가 많을수록 성능이 저하된다.
  • FlatList: 화면에 보이지 않는 리스트들은 메모리에서 제거하고 화면에 보이는 부분들만 렌더링하여 리스트가 많이 있어도 성능 저하를 최소화시킨다. (무한스크롤 적용에 적합)

주요 Props

  • data : 데이터를 받아 올 곳을 입력하는 곳
  • renderItem : [data]에서 항목을 가져와 목록으로 렌더링
  • keyExtractor : JavaScript에서 'Key'와 같은 기능. 지정된 index에서 지정된 항목의 고유 키를 추출하는 데 사용.

공식 문서 https://reactnative.dev/docs/flatlist

참고 https://velog.io/@st2702/React-Native-FlatList

 

 

Liniking으로 링크 연결하기

const openYoutube = async (key) => {
    const url = `https://www.youtube.com/watch?v=${key}`;
    await Linking.openURL(url);
}

Linking 컴포넌트를 이용해 외부 URL 링크를 열 수 있다. 만약에 유튜브 어플이 설치되어 있다면 바로 어플로 연결되고 설치되어 있지 않다면 웹 브라우저에서 링크가 열린다.

 

 

param 받아서 페이지 연결하기

const { navigate } = useNavigation();

<MovieContainer 
    onPress={() => navigate("Stacks", {
        screen: "Detail",
        params: { movieId: movie.id }
    })}
>

해당 요소를 클릭했을 때 이동할 페이지를 지정하고 params를 넘긴다.

 

const Detail = ({ navigation: { navigate }, route: { params: { movieId }}}) => {
	...생략...
};

클릭했을 때 이동하는 목적지인 컴포넌트는 route에서 params를 받는다.

 

 

StatusBar 텍스트 색상 조정하기

const isDark = useColorScheme() === "dark";

<StatusBar style={isDark ? "light" : "dark"} />

다크 모드로 변환했을 때 상단바가 전부 까매져서 시간이나 배터리 부분이 보이지 않아서 StatusBar 컴포넌트를 이용해서 색상을 조정했다. 저 isDark라는 녀석 다크모드 구현할 때 여기저기 유용하게 사용할 수 있다!

 


Programmers 문제 풀기

아이스 아메리카노

나의 풀이

function solution(money) {
    let answer = [];
    answer.push(parseInt(money / 5500))
    answer.push(money % 5500)
    return answer
}

 

다른 사람의 풀이

function solution(money) {
    return [Math.floor(money / 5500), money % 5500];
}

안 그래도 문제 풀면서 배열에 한번에 추가할 수 있는 방법이 없을까 생각했었는데 그냥 배열에 바로 넣으면 되는 거였구나... 이 풀이의 포인트는 배열 안에서 답을 바로 계산했다는 것!

  • Math.floor() 함수는 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환한다.

 


회고

어제 UI 지옥에서 벗어나서 오늘은 API 이용해서 가져온 정보를 화면에 뿌려주는 공부를 했는데 이게 훨씬 재밌다. 그나저나 네이티브는 수정할 때마다 에러가 뜬다. 그래도 오늘은 꽤나 집중해서 공부했기 때문에 9시 전에 오늘 분량을 다 마칠 수 있었다. 네이티브 공부하면서 느낀 점이 앱은 페이지 이동이 가장 중요한 부분인 거 같다. 그래도 공부하다 보니까 앱 개발도 매력이 있는 거 같기도 하고.. 흐음...