[TIL-43] React-컴포넌트 재사용

da.circle·2022년 10월 26일
0

TIL

목록 보기
43/44

컴포넌트를 재사용해보자!

지금까지 리액트를 공부하면서 나도 모르게 컴포넌트를 재사용하고 있던 것 같다!
하지만 여태 재사용한 걸 보면 텍스트 빼고는 나머지가 완전히 동일한 요소만 컴포넌트 재사용을 해왔다.
이번에는 props로 필요한 데이터를 넘기고, 조건부 렌더링을 통해서 비슷하게 생기고 약간 다르게 생긴 요소들을 만들어봤다.
+과제 코드가 긴 것 같아서 조금 짧게 바꿔봤다.

내가 생각한 흐름

  1. 어떤 컴포넌트를 만들어야 할까?
    - 노란 박스 : Card 컴포넌트
    - 초록 박스 : Item 컴포넌트 (잘 보면 카드1과 카드2의 제품들의 레이아웃이 살짝 다르다!)

  1. mock 데이터 만들기
  • 각 카드는 datas 배열 안에 객체로 넣는다.
  • 각 카드의 item은 해당 카드 객체 안에 items 배열 안에 객체로 넣는다.
    (사진은 UnSplash에서 가져왔습니다)
{
  "datas": [
    {
      "id": 1,
      "title": "카드1",
      "content": "카드1에 대한 내용입니다.",
      "cardType": "card",
      "imgUrl": "https://images.unsplash.com/photo-1617043786394-f977fa12eddf?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80",
      "items": [
        {
          "id": 1,
          "name": "제품1-1",
          "price": "900,000",
          "imgUrl": "https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1099&q=80"
        }
      ]
    },
    {
      "id": 2,
      "title": "카드2",
      "content": "카드2에 대한 내용입니다.",
      "cardType": "list",
      "imgUrl": "https://images.unsplash.com/photo-1496181133206-80ce9b88a853?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1171&q=80",
      "items": [
        {
          "id": 1,
          "name": "제품2-1",
          "price": "1,500,000",
          "imgUrl": "https://images.unsplash.com/photo-1661961110372-8a7682543120?ixlib=rb-4.0.3&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
        },
        {
          "id": 2,
          "name": "제품2-2",
          "price": "2,500,000",
          "imgUrl": "https://images.unsplash.com/photo-1559163499-413811fb2344?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
        }
      ]
    }
  ]
}

  1. 데이터를 불러온다
  • CardList.js파일에서 useEffect - fetch()로 데이터를 불러온다. 이때 의존성 배열은 빈 배열로 넣는다. 데이터는 첫 렌더링때만 불러오면 된다.
const [datas, setDatas] = useState([]);
  useEffect(() => {
    fetch("/data/data.json")
      .then((res) => res.json())
      .then((json) => {
        setDatas(json.datas);
      });
  }, []);

  1. CardList.js의 자식 컴포넌트로 Card.js를 생성하고, 불러온 datas 배열을 props로 전달한다.
<div className="cardList">
  {datas.map((data) => {
    return <Card data={data} key={data.id} />;
  })}
</div>
  • props를 받아와서 그냥 구조분해할당을 사용하면 되는데 그 생각을 못하고 useEffect를 사용해서 state에 저장했다.
//내가 짠 코드
const [items, setItems] = useState([]);
  useEffect(() => {
    setItems(data.items);
  }, [data.items]);

//구조분해할당으로 짠 코드
const { imgUrl, cardType, title, content, items } = data;

  1. Card 컴포넌트의 자식 컴포넌트로 Item.js를 생성하고, props로 필요한 데이터 전달하기
  • data 객체에서 items 배열과 item의 className을 구분하기 위한 cardType을 넘겨준다.
  • 과제에서는 items가 없는 카드도 있었다. items가 없는 카드가 있다면 items의 유무에 따라서 Item컴포넌트를 그릴지 말지 결정한다.
<ul>
  {items &&
    items.map((item) => {
      return <Item item={item} key={item.id} type={cardType} />;
    })}
</ul>
          

  1. Card컴포넌트에서 받은 props를 가지고 Item.js 코드를 작성한다.
  • 첫번째 카드의 item의 className은 list이고, 두번째 카드의 className은 card이다.
    → 태그의 속성에도 직접 데이터바인딩이 가능하다.
{/*li태그의 className이 item list / item card가 될 수 있도록 데이터바인딩*/}
<li className={"item " + type}>
  <img alt="item" src={imgUrl} />
  <div className="content">
    <div>
      <p>{name}</p>
      <p className="price">{price}</p>
    </div>
  </div>
</li>
  • 나는 처음에 위 방법을 생각 못하고 조건부 렌더링을 사용해서 코드를 작성했다.
//내 부끄러운 길다란 코드

{type === "list" ? (
  {/*type === "list"가 true이면 여기 코드 실행*/}
  <li className="item list">
    <img alt="item" src={item.imgUrl} />
    <div className="content">
      <div>
        <p>{item.name}</p>
        <p className="price">{item.price}</p>
      </div>
      <button className="button" />
    </div>
  </li>
      ) : (
  {/*type === "list"가 false이면 여기 코드 실행*/}
  <li className="item card">
    <img alt="item" src={item.imgUrl} />
    <div className="content">
      <div>
        <p>{item.name}</p>
        <p className="price">{item.price}</p>
      </div>
      <button className="button" />
    </div>
  </li>
)}

  1. css코드도 컴포넌트마다 나눠줘야 한다!
  • Card.scss파일과 Item.scss 파일로 나눈다.

컴포넌트를 재사용하지 않고 하드코딩한다면?

//카드 1번만 구현한 코드입니다..
const noReuse = () => {
  return (
    <div className="cardList">
      <article className="card">
        <div className="cardImg">
          <img
            alt="cardImg"
            src="https://images.unsplash.com/photo-1617043786394-f977fa12eddf?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"
          />
        </div>
        <div className="cardMain">
          <h3>카드1</h3>
          <div>
            <p>카드1에 대한 내용입니다.</p>
          </div>
          <ul>
            <li className="item list">
              <img
                alt="item"
                src="https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1099&q=80"
              />
              <div className="content">
                <div>
                  <p>제품1-1</p>
                  <p className="price">900,000</p>
                </div>
              </div>
            </li>
          </ul>
        </div>
      </article>
      {/*여기에 카드 2번 <article>태그부터 시작해서 엄청 긴 코드가 또 들어갑니다..*/}
    </div>
  );
};

결론 : 컴포넌트 재사용이 가능한 UI라면 재사용하는 것이 좋다..!!

profile
프론트엔드 개발자를 꿈꾸는 사람( •̀ ω •́ )✧

0개의 댓글