[Project - 웹앱] React Children 사용해보자!

choi seung-i·2022년 8월 20일
0

작업로그

목록 보기
11/18
post-thumbnail

부캠에서 children에 대해서 세션을 들었던 적이 있었는데,
그때는 이걸 사용 할 일이 많을까? 너무 복잡해 보이는데 ... 라고 생각만하고 지나쳤었다.

회사에서 프로젝트를 하다보니 그동안과는 다르게 많은 페이지를 다루면서 비슷한 내용을 다루는 페이지 별 공용 레이아웃이 필요하다는 것을 느꼈다.


project : commerce web app
stack : #React #styled-component #TypeScript #Zustand


페이지 별 공용 레이아웃 Children으로 만들기

상단에 뒤로가기 버튼과 장바구니가 있는 공용 TopBar 컴포넌트가 위치하고 기간 선택하는 셀렉트박스까지 공용 사용 부분이었다.
children으로 선택한 기간에 대한 리스트를 뿌려주는것으로 작업!

/*children 받아서 사용하는 레이아웃 컴포넌트*/
interface Props {
  title: string;
  children: ReactNode;
}

const OrderLayout = ({ title, children }: Props) => {
  return (
    <PageWrap>
      <TopBar />
      <Title>{title}</Title>
      <PeriodWrap>
        <PeriodSelect>
          <Period>최근 3개월</Period>
          <Period>최근 6개월</Period>
          <Period>최근 1</Period>
        </PeriodSelect>
      </PeriodWrap>
      <ListContainer>{children}</ListContainer>
    </PageWrap>
  );
};
  • 우선 공용으로 사용 될 부분인 OrderLayout 컴포넌트를 생성
  • ListContainer 내에 List가 들어갈 예정으로 {children} 자리를 만들어 주었다.
  • select 값은 전역상태관리를 통해 cildren 리스트 뿌리는 곳에서 사용 할 예정!
  • typescript 사용을 할 때 방법은 몇가지가 있는데, ReactNode로 사용!

import React 사용 여부!

children: ReactNode
=> import React, { ReactNode } from "react";
children: React.ReactNode
=> import React from "react";

  • ReactNode는 react안에 포함된 것으로 편한대로 사용
/*레이아웃 컴포넌트 사용하는 페이지*/
const OrderHistory = () => {

  useEffect(() => {
    //... listData 가져오기 생략
  }, [])
  
  return (
    <OrderLayout title="주문 내역 조회">
      {listData.length ? (
        listData.map((data) => (
          <OrderList key={data.id} productdata={data}/>
        )
      ) : (
        <EmptyView desc="상품이 없어요" />
      )}
    </OrderLayout>
  );
};
  • <OrderLayout> {이 부분에 들어가는 것이 children} </OrderLayout>
  • 데이터가 없을 땐 EmptyView 컴포넌트를 보여주고, 데이터가 있을 땐 map시켜준다.

데이터 교체가 아닌 children으로 한 이유 ?

리스트의 카드레이아웃이 페이지별로 조금씩 달랐기 때문에 그 부분은 공통으로 사용하기 보단 children으로 사용하는게 좋을 것 같다고 판단하였다.

toggle list도 children 사용해보기!

/*children 받아서 사용하는 toggle 컴포넌트*/
const Toggle = ({ title, children }: Props) => {
  const [isOpen, setIsOpen] = useState(false);

  const handleToggle = (e: any) => {
    setIsOpen((prev) => !prev);
  };

  return (
    <Toggle>
      <Btn onClick={handleToggle}>
        {title}
        <ToggleArrow isOpen={isOpen} />
      </Btn>
      <Content isOpen={!isOpen}>{children}</Content>
    </Toggle>
  );
};
/*toggle 컴포넌트 사용하는 페이지*/
<InfoToggle title="판매자 안내">{"내용"}</InfoToggle>
<InfoToggle title="상품 고시정보">{"내용"}</InfoToggle>

  • 페이지와 동일하게 children을 넣어주는 데 내용 부분이 isOpen={true} 일 때에만 보이도록 해주었다.
  • 응용을 하면 닫혔을 때에 버튼 부분에 요약 내용을 보여주게 할 수도 있다.

응용 : 페이지 레이아웃 children에 children 사용하는 컴포넌트

<OrderLayout
      title="페이지 제목"
    >
      <ListContainer>
        <OrderToggle
          title="구매한 상품"
          desc={"내용"}
          defaultOpen={true}
        >
          <>내용 컴포넌트</>
        </OrderToggle>
        <OrderToggle
          //... 생략
        >
          <>내용 컴포넌트</>
        </OrderToggle>
        <OrderToggle
          //... 생략
        >
          <>내용 컴포넌트</>
        </OrderToggle>
        {/* 생략 */}
      </ListContainer>
    </OrderLayout>
  • 2중? 중첩? 사용 : 위에서 사용했던 OrderLayout 컴포넌트의 cildren으로 orderToggle 컴포넌트를 사용하고 토글의 내용컴포넌트를 cildren으로 넘겨주었다.

🧐 느낀 점

공통으로 사용하는 페이지가 5개인데 한번 레이아웃컴포넌트를 잡아두니, 재사용 할 수 있어서 빠르게 작업을 할 수 있었다.
그리고 가장 좋은점은 수정사항이 있을 때 해당 레이아웃컴포넌트만 수정하면 되는 부분이다.

페이지 레이아웃을 만들어 보니 공용으로 사용하는 컴포넌트 내에서 children을 사용하면 더욱 다양하게 공용컴포넌트로 만들어 둘 수가 있겠다는 생각도 하였고, 그래서 toggle list도 children을 사용한 컴포넌트화 시킬 수 있었다.

그동안 일반 컴포넌트로 작업 한 부분에서도 children 사용하면 좋을 것 같은데? 싶은 부분들도 눈에 보여서, 해당 부분은 나중에 리팩토링 때 다듬고 싶은 부분이다.

(children에대해 검색하다 보니 카카오 기술블로그 21년 글도 찾게되어서 좀더 다양하게 사용할 수 있는 방법을 알아두면 좋을 것 같아서 레퍼 첨부!)


reference

react children with typescript
카카오 엔터 기술블로그 - React Children과 친해지기


공부하며 정리&기록하는 ._. 씅로그

profile
Front-end

0개의 댓글