250x250
반응형
arkhyeon
arkhyeon
arkhyeon
전체 방문자
오늘
어제
  • 분류 전체보기 (88)
    • Spring (5)
    • Java (4)
    • React (25)
      • TypeScript (6)
      • JavaScript (1)
      • Jest (9)
    • NEXT (8)
    • SQL (1)
    • React native (1)
    • CSS (3)
    • Web (1)
    • Git (3)
    • ETC (6)
    • 빅데이터DB (8)
    • Docker (4)
    • Tool (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • react loading
  • websocket
  • node WebSocket
  • Spring WebSocket
  • websocket server
  • react
  • react usetransition
  • usetransition
  • javasciprt websocket
  • react19
  • HIVE
  • react spring websocket
  • javascript wss
  • jest
  • docker tomcat
  • kudu
  • react websocket
  • WSS
  • react jest
  • react typescript

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
arkhyeon

arkhyeon

React

Compound Component 패턴

2023. 7. 12. 10:26
728x90
반응형

React Bootstrap과 동일한 패턴을 작성하고 싶었다.

# 문제점

이전 컴포넌트의 구성은 ModalBody의 children을 제외한 Header[Title], Footer이 파라미터로 들어가 정해진 구성으로 들어가 일관성 있는 UI를 나타낼 수 있지만 다른 구성 및 스타일로 바꾸기 힘들고 하나의 컴포넌트가 많은 파라미터를 받아 해당 파라미터가 어디에 관련이 있는지 알기 어렵다.

<ModalTemplate
      modalState={modalState}
      handleClose={handleClose}
      modalTitle="레이아웃 추가"
      width="600px"
      buttonList={[
        <WhiteButton onClick={handleClose}>닫기</WhiteButton>,
        <BlackButton onClick={insertLayout}>저장</BlackButton>,
      ]}
    >
	<div>모달입니다.</div>
</ModalTemplate>

장점

  • 자유롭게 컴포넌트를 구성 및 스타일 변경이 가능하다.
  • 서브 네임으로 구획을 정확히 나눌 수 있다.
  • 서브 컴포넌트의 파라미터 배분으로 정갈한 코드를 작성할 수 있다.

단점

자유도가 높은 만큼 사용자가 컴포넌트 구성의 이해가 필요하고 예상하지 못한 동작이 일어날 가능성이 있다.

# Compound Component 구성

<Modal open={open} handleClose={() => setOpen(false)}>
        <Modal.Header closeButton>모달헤더</Modal.Header>
        <Modal.Body>모달입니다.</Modal.Body>
        <Modal.Footer>
		<WhiteButton onClick={handleClose}>닫기</WhiteButton>
	        <BlackButton onClick={insertLayout}>저장</BlackButton>
	</Modal.Footer>
</Modal>

# Compound Component 코드

import styled from '@emotion/styled';
import { createContext, useContext } from 'react';
import { IoClose } from 'react-icons/io5';
import { createPortal } from 'react-dom';

const ModalContext = createContext(null);

const Modal = ({ open, handleClose, children }) => {
  const contextValue = { open, handleClose };
  return (
    <ModalContext.Provider value={contextValue}>
      {open &&
        createPortal(
          <ModalWrap>
            <ModalBackDrop onClick={handleClose} />
            <ModalContent>{children}</ModalContent>
          </ModalWrap>,
          document.body,
        )}
    </ModalContext.Provider>
  );
};

const ModalHeader = ({ closeButton, children }) => {
  const { handleClose } = useContext(ModalContext);
  return (
    <ModalHeaderWrap>
      {children}
      {closeButton && <IoClose onClick={handleClose} />}
    </ModalHeaderWrap>
  );
};

const ModalBody = ({ children }) => {
  return <ModalBodyWrap>{children}</ModalBodyWrap>;
};

const ModalFooter = ({ children }) => {
  return <ModalFooterWrap>{children}</ModalFooterWrap>;
};

//...Styled CSS 제거...

export default Object.assign(Modal, {
  Header: ModalHeader,
  Body: ModalBody,
  Footer: ModalFooter,
});
728x90
반응형

'React' 카테고리의 다른 글

React 빌드 용량 최적화 - Vite rollupOptions manualChunks  (0) 2023.09.07
Dynamic Import / Lazy Loading - 코드 스플리팅[Code Splitting]  (0) 2023.09.07
React createPortal(Modal Component)  (0) 2023.07.11
React Route dom v6 하위 경로 이동 시 에도 인덱스 NavLink 활성화  (0) 2023.07.04
JEST-REACT18-Vite  (0) 2023.05.22
    'React' 카테고리의 다른 글
    • React 빌드 용량 최적화 - Vite rollupOptions manualChunks
    • Dynamic Import / Lazy Loading - 코드 스플리팅[Code Splitting]
    • React createPortal(Modal Component)
    • React Route dom v6 하위 경로 이동 시 에도 인덱스 NavLink 활성화
    arkhyeon
    arkhyeon

    티스토리툴바