인프런 커뮤니티 질문&답변

inchang0326님의 프로필 이미지
inchang0326

작성한 질문수

비전공자를 위한 진짜 입문 올인원 개발 부트캠프

메인 화면 구현 - 3

width must be speified for horizontal carousels 오류

해결된 질문

작성

·

254

·

수정됨

1

안녕하세요.

react-native-reanimated-carousel 사용 시,

carousel의 prop으로 width를 정의했는데도,

제목 처럼 "width must be speified for horizontal carousels" 오류가 발생합니다.

어떻게 해결할 수 있을까요??

 

강의 클론코딩 했는데, 위 오류에 앞서 "PanGestureHandler must be used as a descendant of GestureHandlerRootView" 오류가 발생했었는데, 인터넷 검색 결과로 <SafeAreaView> 바깥에 <GestureHandlerRootView> 선언하여 해결했는데, 이 영향도 일까요??

 

코드 첨부합니다.

import { StatusBar } from "expo-status-bar";
import { API_URL } from "./config/constant";
import avatarImg from "./assets/icons/avatar.png";
import React from "react";
import {
  StyleSheet,
  Text,
  View,
  Image,
  ScrollView,
  Dimensions,
  TouchableOpacity,
  Alert,
  SafeAreaView,
} from "react-native";
import Carousel from "react-native-reanimated-carousel";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import axios from "axios";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import "dayjs/locale/ko";

dayjs.extend(relativeTime);
dayjs.locale("ko");

export default function App() {
  const [products, setProducts] = React.useState([]);
  const [banners, setBanners] = React.useState([]);

  React.useEffect(() => {
    axios
      .get(`${API_URL}/products`)
      .then(function (result) {
        const products = result.data.products;
        setProducts(products);
      })
      .catch(function (error) {});

    axios
      .get(`${API_URL}/banners`)
      .then(function (result) {
        const banners = result.data.banners;
        setBanners(banners);
      })
      .catch(function (error) {});
  }, []);

  return (
    <GestureHandlerRootView>
      <SafeAreaView style={styles.safeAreaView}>
        <View style={styles.container}>
          <ScrollView>
            <Carousel>
              data={banners}
              width={Dimensions.get("window").width}
              height={200}
              autoPlay={true}
              sliderWidth={Dimensions.get("window").width}
              itemWidth={Dimensions.get("window").width}
              itemHeight={200}
              renderItem=
              {(obj) => {
                retrun(
                  <TouchableOpacity
                    onPress={() => {
                      Alert.alert("배너 클릭");
                    }}
                  >
                    <Image
                      style={styles.bannerImage}
                      source={{ uri: `${API_URL}/${obj.item.img_url}` }}
                    />
                  </TouchableOpacity>
                );
              }}
            </Carousel>
            <Text style={styles.headline}>판매되는 상품들</Text>
            <View style={styles.productList}>
              {products.map((product, index) => {
                return (
                  <View key={index} style={styles.productCard}>
                    {product.status === "02" && (
                      <View style={styles.productBlur} />
                    )}
                    <View>
                      <Image
                        style={styles.productImg}
                        source={{
                          uri: `${API_URL}/${product.img_url}`,
                        }}
                        resizeMode={"contain"}
                      />
                    </View>
                    <View style={styles.productContents}>
                      <Text style={styles.productName}>{product.name}</Text>
                      <Text style={styles.productPrice}>{product.price}원</Text>
                      <View style={styles.productFooter}>
                        <View style={styles.productSeller}>
                          <Image
                            style={styles.productAvatar}
                            source={avatarImg}
                          />
                          <Text style={styles.productSellerName}>
                            {product.seller}
                          </Text>
                        </View>
                        <Text style={styles.productDate}>
                          {dayjs(product.created_at).fromNow()}
                        </Text>
                      </View>
                    </View>
                  </View>
                );
              })}
            </View>
          </ScrollView>
        </View>
      </SafeAreaView>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  headline: {
    fontSize: 24,
    fontWeight: "800",
    marginTop: 10,
    marginBottom: 10,
  },
  container: {
    flex: 1,
    backgroundColor: "#fff",
    paddingTop: 32,
    margin: 10,
  },
  productCard: {
    width: "100%",
    borderColor: "rgb(230,230,230)",
    borderWidth: 1,
    borderRadius: 16,
    backgroundColor: "white",
    marginBottom: 10,
  },
  productBlur: {
    position: "absolute",
    top: 0,
    bottom: 0,
    right: 0,
    left: 0,
    backgroundColor: "#ffffffaa",
    zIndex: 999,
  },
  productImg: {
    width: "100%",
    height: 210,
  },
  productContents: {
    padding: 8,
  },
  productSeller: {
    flexDirection: "row",
  },
  productAvatar: {
    width: 24,
    height: 24,
  },
  productFooter: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    marginTop: 12,
  },
  productName: {
    fontSize: 14,
  },
  productPrice: {
    fontSize: 16,
    fontWeight: "600",
    marginTop: 8,
  },
  productSellerName: {
    fontSize: 14,
  },
  productDate: {
    fontSize: 14,
  },
  productList: {
    alignItems: "center",
  },
  bannerImage: {
    width: "100%",
    height: 200,
  },
  safeAreaView: {
    flex: 1,
    backgroundColor: "#fff",
  },
});

답변 1

1

안녕하세요, 인프런 AI 인턴입니다.

react-native-reanimated-carousel에서 width를 정의했으나 오류가 발생하는 경우는 대부분 prop이 올바르게 전달되지 않았을 때 나타납니다. 코드를 살펴본 결과, <Carousel> 컴포넌트의 prop 들이 JSX의 중괄호 {} 안에 들어가지 않은 것을 확인할 수 있습니다.

Carousel 컴포넌트에 prop을 전달할 때는 아래와 같이 중괄호를 사용하여 JavaScript 표현식으로 감싸줘야 합니다:

<Carousel
  data={banners}
  width={Dimensions.get("window").width}
  height={200}
  autoPlay={true}
  sliderWidth={Dimensions.get("window").width}
  itemWidth={Dimensions.get("window").width}
  itemHeight={200}
  renderItem={(obj) => {
    return (
      // ... renderItem 내부 구현
    );
  }}
/>

또한 코드 내에 오탈자가 있습니다. retrunreturn이 되어야 정상적인 함수 반환을 할 수 있습니다.

이 변경사항을 적용한 후 다시 실행해 보시길 권장합니다. 이 과정에서 PanGestureHandler must be used as a descendant of GestureHandlerRootView 오류는 이미 해결하셨기 때문에 연관성은 없을 것으로 보입니다. 오류가 계속 발생한다면, carousel 관련 prop들이 정확히 전달되고 있는지 확인해 보시고, 필요하다면 react-native-reanimated-carousel 공식 문서나 관련 커뮤니티를 참조하여 추가적인 도움을 받으시길 바랍니다.

inchang0326님의 프로필 이미지
inchang0326
질문자

답변 주신 내용으로 해결했습니다.

감사합니다.

inchang0326님의 프로필 이미지
inchang0326

작성한 질문수

질문하기