리액트 컴포넌트 재사용, 과제 리뷰

라용·2022년 9월 14일
0

위코드 - 스터디로그

목록 보기
42/100
post-custom-banner

위코드에서 공부하며 정리한 내용입니다.

과제

하나의 코드로 작성된 카드 UI 를 컴포넌트로 분리하고 카드뷰와 리스트뷰로 구분해 사용할 수 있게 만듭니다.

풀이

우선 반복되는 카드 디자인을 Mock 데이터와 map 메서드로 만듭니다. Mock 데이터는 U에서 변경되는 요소를 고려해 json 파일로 만듭니다.

[
  {
    "id": 1,
    "tag": "NEW",
    "img": "https://t1.kakaocdn.net/friends/prod/main_tab/home/home_20201103134054_kr.jpg?type=thumb&opt=R329x247@2xa",
    "title": "촉촉함을 원해요",
    "desc": "재채기는 콜록 콜록 눈,코,입 모두 간질 간질. 이게 다 건조함때문이라구! 건조함을 해결하러 온 꿀꿀꿀귀탱 가습기들, 구경해볼까요?"
  },
  {
    "id": 2,
    "tag": "Good",
    "img": "https://t1.kakaocdn.net/friends/prod/main_tab/home/home_20201106164745_kr.jpg?type=thumb&opt=R329x247@2xa",
    "title": "통통미 폭발 구름 폭신 필로우",
    "desc": "통통하고 말랑 말랑한 너희에게 내 하루 시작과 끝에서 힐링을 부탁해!"
  },
  {
    "id": 3,
    "tag": "Theme",
    "img": "https://t1.kakaocdn.net/friends/prod/main_tab/home/home_20201111183631_kr.jpg?type=thumb&opt=R335x187@2xa",
    "title": "올 겨울엔 프렌즈랑 메리 화이트 크리스마스!",
    "desc": "올해 크리스마스엔 눈이 올까요? 안오면 어때요. 이미 프렌즈들이 내 마음에 하얀 눈을 내려주고 있는걸!"
  }
]

useState 와 useEffect, fetch 를 사용해 데이터를 가져와 상태값에 저장합니다.

const [cardInfoList, setCardInfoList] = useState([]);

useEffect(() => {
fetch("/data/cardInfo.json") // 데이터 위치 신경쓰기
  .then((res) => res.json())
  .then((result) => setCardInfoList(result));
}, []); // 의존성 배열 비워두기

가져온 데이터를 map 메서드로 돌려 반복되는 카드 UI 만듭니다. 카드 UI 는 Card 컴포넌트를 만들어서 구현하고 props 로 데이터를 전달합니다.

{cardInfoList.map((cardInfo) => {
  return (
    <Card
   		key={cardInfo.id} // 키 값 지정해야 함
        id={cardInfo.id}
		tag={cardInfo.tag}
		img={cardInfo.img}
		title={cardInfo.title}
		desc={cardInfo.desc}
	/>
  );
})}

Card 컴포넌트는 props 로 전달받은 데이터로 카드 UI 를 그립니다.

const Card = ({ id, tag, img, title, desc}) => {
  return (
    <article className="card">
      <div>
        <img alt="card" src={img} />
      </div>
      <div className="cardMain">
        <div>
          <span className={tag.toLowerCase()}>{tag}</span>
        </div>
        <h3>{title}</h3>
        <div>
          <p>{desc}</p>
        </div>
      </div>
    </article>
  );
};

이제 카드 하단에 제품 목록이 들어가는 컴포넌트를 만듭니다. 우선 제품 정보를 담은 Mock 데이터를 json 형태로 준비하고

[
  {
    "id": 1,
    "img": "https://t1.daumcdn.net/friends/prod/product/20201020152815054_8809721505908_AW_00.jpg?type=thumb&opt=R103x103@2xa",
    "title": "구름폭신필로우_라이언",
    "price": "39,000원"
  },
  {
    "id": 2,
    "img": "https://t1.daumcdn.net/friends/prod/product/20201020152804391_8809721505915_AW_00.jpg?type=thumb&opt=R103x103@2xa",
    "title": "구름폭신필로우_어피치",
    "price": "42,000원"
  },
  {
    "id": 3,
    "img": "https://t1.daumcdn.net/friends/prod/product/20201020152905998_8809721505922_AW_00.jpg?type=thumb&opt=R103x103@2xa",
    "title": "구름폭신필로우_무지",
    "price": "15,000원"
  }
]

이 데이터 역시 useEffect, fetch 함수로 호출한 후 상태값에 넣어줍니다.

const [itemInfoList, setItemInfoList] = useState([]);

useEffect(() => {
  fetch("/data/itemInfo.json")
    .then((res) => res.json())
    .then((result) => setItemInfoList(result));
}, []);

해당 데이터를 Card 컴포넌트에 props로 전달하고,

{cardInfoList.map((cardInfo) => {
    return (
      <Card
        key={cardInfo.id}
        id={cardInfo.id}
        tag={cardInfo.tag}
        img={cardInfo.img}
        title={cardInfo.title}
        desc={cardInfo.desc}
        itemInfoList={itemInfoList} // 여기 추가
      />
    );
})}

Card 컴포넌트에서 tag 이름에 따라 리스트뷰, 카드뷰 컴포넌트를 화면에 보여지게 만듭니다. {tag === "Good" && } 이렇게 입력하면 tag 이름에 따라 해당 컴포넌트가 화면에 그려집니다. 아래 공식은 해당 컴포넌트를 바로 넣지 않고 map 함수로 반복되는 구조를 리턴했습니다.

<ul>
  {tag === "Good" &&
    itemInfoList.map((itemInfo) => {
      return <ItemListView key={itemInfo.id} itemInfo={itemInfo} />;
    })}
  {tag === "Theme" &&
    itemInfoList.map((itemInfo) => {
      return <ItemCardView key={itemInfo.id} itemInfo={itemInfo} />;
    })}
</ul>

리스트 뷰와 카드뷰의 구조는 클래스 이름만 다르게 해서 다른 scss 를 적용하면 되지만, 이후 사용성을 고려해 컴포넌트 파일과 각각의 scss 파일을 두개로 분리했습니다. 아래는 리스트뷰 컴포넌트 입니다.

const ItemListView = ({ itemInfo }) => {
  const { img, title, price } = itemInfo;
  return (
    <li className="item list"> // 카드뷰는 "item card"
      <img alt="item" src={img} />
      <div>
        <div>
          <p>{title}</p>
          <p className="price">{price}</p>
        </div>
        <button className="button" />
      </div>
    </li>
  );
};
profile
Today I Learned
post-custom-banner

0개의 댓글