본문 바로가기

react

[소플] ch 13. 합성 vs 상속

1. 합성에 대해 알아보기 

 

합성(Composition)

 

- 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것

- 조합 방법에 따라 합성의 사용기법이 나눠짐

 

1) Containment

 

- 하위 컴포넌트를 포함하는 형태의 합성 방법

 

- 사이드바(Sidebar)나 다이얼로그 (Dialog)같은 박스 형태의 컴포넌트는 자신의 하위 컴포넌트를 미리 알 수 없음

  -> 해당 컴포넌트를 사용하는 개바라가 어떤 것을 넣는냐에 따라 하위 컴포넌트가 달라지기 때문

  -> Containment 방법을 사용하여 합성을 사용 

 

- Containment를 사용하는 방법은 리액트 컴포넌트의 props에 기본적으로 들어 있는 children 속성 사용 

- props.children를 통해 하위 컴포넌트를 하나로 모아서 제공 

- props.children을 사용하면 해당 컴포넌트의 하위 컴포넌트가 모두 children으로 들어오게 됨 

 

 

FancyBorder 컴포넌트 

 

- 자신의 하위 컴포넌트를 모두 포함(Containment)하여 예쁜 테두리로 감싸주는 컴포넌트 

 

function FancyBorder(props) {
     return (
    	<div className={'FancyBorder FancyBorder-' + props.color}>
        	{props.childern}
        </div>
    );
}

 

WelcomDialog 컴포넌트 

 

- FancyBorder 컴포넌트로 감싸진 부분 안에는 <h1>과 <p> 두개의 태그가 들어 있음

- 두 개의 태그 (<h1>, <p>)는 모두 FancyBorder 컴포넌트에 children라는 이름의 props로 전달

function WelcomeDiaglog(props) {
    return (
    	<FancyBorder color="blue">
        	<h1 className = "Dialog-title">
            	어서오세요.
            </h1>
            <p className="Dialog-message">
            	우리 사이트에 방문하신 것을 환영합니다!
            </p>
        </FancyBorder>
    );
}

 

- 여러 개의 children 집합이 필요한 경우는 별도로 props를 정의해서 각각 원하는 컴포넌트를 넣어주면 됨 

 

SplitPane 컴포넌트 

 

- 화면을 왼쪽과 오른쪽으로 분할해서 보여줌

- App 컴포넌트에서 left, right 라는 두개의 props를 정의하여 그 안에 각각 다른 컴포넌트를 넣어줌 

- SplitPane에서는 이 left, rightㄹ르 props로 받게 되고 각각 화면의 왼쪽과 오른쪽에 분리해서 렌더링 

 

function SplitPane(props) {
    return (
        <div className="SplitPan">
            <div className="SplitPan-left">
                {props.left}
            </div>
            <div className="SplitPan-right">
                {props.right}
            </div>
        </div>
    );
}

function App(props) {
    return (
        <SplitPane  
            left={
                <Contacts />
            }
            right={
                <Chat />
            }
        />
    );
}

 

 

2) Specialization 

 

- 범용적인 개념을 구별이 되게 구체화하는 것 

- 범용적으로 쓸 수 있는 컴포넌트를 만들어 놓고 이를 특수화시켜서 컴포넌트를 사용하는 합성 방식 

- 기존의 객체지향 언어에서는 상속을 사용하여 Specialization을 구현하나 리액트에서는 합성을 사용하여 Specialization 구현 

 

ex)

 

- WlecomeDialog는 Dialog의 특별한 케이스

- Dialog 컴포넌트는 title과 message라는 두 가지 props를 갖고 있는데 각각의 다이얼로그에 나오는 제목과 메시지를 의미 

- Welcome 컴포넌트에서는 제목을 '어서오세요'라고 짓고 사이트에 접속한 사용자에게 인사말을 하는 다이얼로그 

 

function Dialog(props) {
    return (
        <FancyBorder color="blue">
            <h1 className="Dialog-title">
                {props.title}
            </h1>
            <p className="Dialog-message">
                {props.message}
            </p>
        </FancyBorder>
    );
}

function WelcomeDialog(props) {
    return (
        <Dialog
            title="어서 오세요"
            message="우리 사이트에 방문하신 것을 환영합니다."
        />
    );
}

 

3) Containment와 Specialization을 같이 사용하기 

 

- Containement를 위해서 props.children을 사용하고 Specilalization을 위해 직접 정의한 props를 사용

 

ex)

 

- Dialog 컴포넌트 끝부분에 props.children을 통해 하위 컴포넌트가 다이얼로그 하단에 렌더링됨 

- SignUpDialog 컴포넌트를 보면 Specializaiton을 위한 props인 title, message에 값을 넣어주고 있으며 사용자로부터 닉네임을 입력받고 가입하도록 유도하기 위해 <input>과 <button> 태그가 들어 있음 

- 두 개의 태그 (<input>, <button>)는 모두 props.children으로 전달되어 다이얼로그에 표시 

 

function Dialog(props) {
    return (
        <FancyBorder color="blue">
            <h1 className="Dialog-title">
                {props.title}
            </h1>
            <p className="Dialog-message">
                {props.message}
            </p>
            {props.children}
        </FancyBorder>
    );
}

function SignUpDialog(props) {
    const [nickname, setNickname] = useState('');

    const handleChange = (event) => {
        setNickname(event.target.value);
    }

    const handleSignUp = () => {
        alert(`어서오세요, ${nickname}님!`);
    }

    return (
        <Dialog 
            title="화성 탐사 프로그램"
            message="닉네임을 입력해 주세요">
            <input 
                value={nickname}
                onChange={handleChange} />
            <button onClick={handleSignUp}>
                가입하기 
            </button>
        </Dialog>
    );
}

 

 

2. 상속에 대해 알아보기 

 

상속(inheritance)

 

- 객체지향 프로그래밍에서 나온 개념으로 부모 클래스를 상속방아서 새로운 자식 클래스를 만듬

- 자식 클래스는 부모 클래스가 가진 변수나 함수 등의 속성을 모두 갖게됨

 

- 상속을 사용하여 컴포넌트를 만드는 것을 추천할 만한 사용 사례를 찾지 못함

- 리액트에서는 상속 방법을 사용하는 것보다는 합성을 사용하는 것을 권고  

 

 

3. 실습 - card 컴포넌트 만들기 

 

card 컴포넌트 

 

- 하위 컴포넌트를 감싸서 카드 형태로 보여주는 컴포넌트 

- children을 사용한 부분이 Containment이고 title과 background를 사용한 부분이 Specialization

 

function Card(props) {
    const {title, backgroundColor, children} = props;

    return (
        <div
            style={{
                margin: 8, 
                padding: 8,
                borderRadius: 8,
                boxShadow: "0px 0px 4px grey", 
                backgroundColor:backgroundColor || "white",
            }}
        >
            {title && <h1>{title}</h1>}
            {children}
        </div>
    );
}

export default Card;

 

ProfileCard 컴포넌트 

 

- Card 컴포넌트를 사용하여 title에 이름을 넣고, backtroundColor를 녹색으로 설정 

- children으로는 간단한 소개 글을 넣음

 

import Card from "./Card";

function ProfileCard(props) {
    return (
        <Card title="Jiwoo" backgroundColor="green">
            <p> 안녕하세요. 지우입니다.</p>
            <p>리액트 공부중입니다.</p>
        </Card>
    );
}

export default ProfileCard;

 

 

'react' 카테고리의 다른 글

[소플] ch 15. 스타일링  (0) 2023.11.01
[소플] ch 14. 컨텍스트  (1) 2023.10.30
[소플] ch 12. State 끌어올리기  (0) 2023.10.30
[소플] ch 11. 폼  (0) 2023.10.29
[소플] ch 10. 리스트와 키  (0) 2023.10.28