Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ksw_devlog

TIL 10주 3일차 본문

TIL

TIL 10주 3일차

kimcoach 2023. 1. 4. 21:13

[ React Native 영화 페이지 UI 만들기]

 

화면과 이미지를 겹치게 하고 싶을 떄

-> style={StyleSheet.absoluteFill}

height="100%" -> 자식이 가진 크기만큼만

 

<ImageBackground style={{ width: "100%", height: "100%" }} source={{ uri: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2/cOwVs8eYA4G9ZQs7hIRSoiZr46Q.jpg" }}></ImageBackground>

--> 이미지 스타일 width, height 값 안 넣어주면 화면에 이미지 안 보임..

 

<Swiper>
        <SwiperChildView>
          <ImageBackground style={{ width: "100%", height: "100%" }} source={{ uri: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2/cOwVs8eYA4G9ZQs7hIRSoiZr46Q.jpg" }}></ImageBackground>
        </SwiperChildView>
      </Swiper>

-> 화면 꽉 채움 -> Swiper에 height 100% 주기

<Swiper height="100%"> // => showPagination, autoplay, loop 등등 추가 가능
        <SwiperChildView>
          <ImageBackground style={{ width: "100%", height: "100%" }} source={{ uri: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2/cOwVs8eYA4G9ZQs7hIRSoiZr46Q.jpg" }}></ImageBackground>
        </SwiperChildView>
        <SwiperChildView>
          <ImageBackground style={{ width: "100%", height: "100%" }} source={{ uri: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2/cOwVs8eYA4G9ZQs7hIRSoiZr46Q.jpg" }}></ImageBackground>
        </SwiperChildView>
        <SwiperChildView>
          <ImageBackground style={{ width: "100%", height: "100%" }} source={{ uri: "https://www.themoviedb.org/t/p/w300_and_h450_bestv2/cOwVs8eYA4G9ZQs7hIRSoiZr46Q.jpg" }}></ImageBackground>
        </SwiperChildView>
      </Swiper>

------

<SwiperChildView>
      <BackgroundImg key={movie.id} style={StyleSheet.absoluteFill} source={{ uri: getImgPath(movie.backdrop_path) }} />
      <LinearGradient style={StyleSheet.absoluteFill} colors={["transparent", "black"]} />
      <Row>
        <Poster source={{ uri: getImgPath(movie.poster_path) }} />
        <Column>
          <Title>{movie.title}</Title>
          <Rating>{movie.vote_average}</Rating>
          <Overview>
            {movie.overview.slice(0, 150)}
            {movie.overview.length > 150 && "..."}
          </Overview>
        </Column>
      </Row>
    </SwiperChildView>
const SwiperChildView = styled.View`
  flex: 1;
  justify-content: flex-end;
  height: ${SCREEN_HEIGHT / 3 + "px"};
  background-color: green;
`;

const BackgroundImg = styled.Image`
  height: 100%;
  width: 100%;
`;

const Row = styled.TouchableOpacity`
  flex: 1;
  flex-direction: row;
  align-items: flex-end;
`;

const Column = styled.View`
  width: 65%;
  margin-left: 10px;
  margin-bottom: 10px;
`;

const Poster = styled.Image`
  width: 100px;
  height: 160px;
  margin-left: 10px;
  margin-bottom: 10px;
`;

const Title = styled.Text`
  font-size: 20px;
  font-weight: 600;
  color: white;
`;

const Rating = styled.Text`
  color: white;
  margin-top: 5px;
  margin-bottom: 5px;
`;

const Overview = styled.Text`
  font-size: 12px;
  color: white;
`;

스타일 컴포넌트를 활용해서 UI 구성, react-native에서 import 안 되도 가능

 

 

 


API 연결

 

async, await, fetch

useEffect, callback, dependency array

 

-----

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

  if (isLoading) {
    return (
      <Loader>
        <ActivityIndicator />
      </Loader>
    );
  }

=> "https://api.themoviedb.org/3/movie/now_playing?api_key=5f416eba9f9b0006b7c1c5159f9a73dd&language=en-US&page=1" 대신 함수 BASE_URL, API_KEY를 ${ }에 넣어주기( + 백틱)

 

<ScrollView>
      <Swiper height="100%" showsPagination={false}>
        {nowPlayings.map((movie) => (
          <SwiperChildView>
            <ImageBackground key={movie.id} style={{ width: "100%", height: "100%" }} source={{ uri: `https://image.tmdb.org/t/p/w500${movie.backdrop_path}` }} />
          </SwiperChildView>
        ))}
      </Swiper>
    </ScrollView>

=> 서버에서 받아온 데이터로 맵 함수를 돌려주고, 이미지 uri는 results 객체 이용

 

const getData = async () => {
    await Promise.all([getNowPlayings(), getTopRated(), getUpcoming()]);
    setIsLoading(false);
  };

getNowPlayings(), getTopRated(), getUpcoming() 

-> 이 세 가지 API 요청이 끝나야 실행, 그리고 setIsLoading 실행

 

----

[RefreshControl]

 

const [refreshing, setRefreshing] = React.useState(false);

  const onRefresh = React.useCallback(() => {
    setRefreshing(true);
    wait(2000).then(() => setRefreshing(false));
  }, []);

 

 <ScrollView
        contentContainerStyle={styles.scrollView}
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
          />

 

---------

[FlatList]

  • ScrollView 모든 리스트들을 한번에 렌더링 해야해서 리스트가 많을 수록 성능이 저하됩니다.
  • FlatList는 화면에 보이지 않는 리스트들은 메모리에서 제거하고 화면에 보이는 부분들만 렌더링하여 리스트가 많이 있어도 성능 저하를 최소화 시킵니다. (무한스크롤 적용에 적합!)

<FlatList> : 자식 컴포넌트 X => <FlatList /> + props를 사용함

데이터 : 배열,

render Item : map함수로 뿌려주는 대신 -> renderItem({item, index, separators});  // callback함수로 표현

<FlatList data={} renderItem={} keyExtractor={} /> // keyExtractor : key 보관

---

<FlatList data={topRateds} renderItem={({item}) => (
        <HCard movie={item} />
      )} keyExtractor={item=>item.id} />

매개변수는 객체, item으로 

 

ItemSeparatorComponent={<View style={{ width: 10 }} />}

-> 카드 각각 거리 띄우기

--

ListHeaderComponent, ListFooterComponent

 

<FlatList
      refreshing={isRefreshing}
      onRefresh={onRefresh}
      ListHeaderComponent={
        <>
          <Swiper height="100%" showsPagination={false}>
            {nowPlayings.map((movie) => (
              <Slide key={movie.id} movie={movie} />
            ))}
          </Swiper>
          <ListTitle>Top Rated Movies</ListTitle>
          <FlatList
            horizontal
            contentContainerStyle={{ paddingHorizontal: 20 }}
            showsHorizontalScrollIndicator={false}
            data={topRateds}
            renderItem={({ item }) => <VCard movie={item} />}
            keyExtractor={(item) => item.id}
            ItemSeparatorComponent={<View style={{ width: 10 }} />}
          />

          <ListTitle>Upcoming Movies</ListTitle>
        </>
      }
      data={upcomings}
      renderItem={({ item }) => <HCard movie={item} />}
      keyExtractor={(item) => item.id}
      ItemSeparatorComponent={<View style={{ height: 10 }} />}
    />

FlatList에서는 refreshControl이 기본으로 내장되어있음

 

-----

구조분해할당

 

 

 

 

 

 

'TIL' 카테고리의 다른 글

TIL 10주 5일차-React Native Project  (0) 2023.01.06
TIL 10주 4일차  (0) 2023.01.05
TIL 10주 2일차  (0) 2023.01.04
TIL 10주 1일차  (0) 2023.01.02
WIL 9주차  (0) 2023.01.02