• 정의

    • **속성(props)**을 받고, **상태(state)**와 메서드를 가짐
    • 반복되는 UI 단위를 위해 사용
    • 가능한 순수함수(독립적)로 작성
    • 데이터 영역과 UI를 분리
    • MyComponent.defaultProps = {}를 통해 기본 속성을 정함
  • 클래스형 컴포넌트(예전)

    • React.Component를 상속받거나 createClass를 사용
    • 생성자, this, render로 구성
    • 생명주기 관리(componentDidmount, componentDidupdate, componentWillUnmount)
  • 함수형 컴포넌트(현재)

    • 간결하고 가벼움
    • 상태와 생명주기가 없음 : React Hook을 사용하여 관리해야 함
      • useState, useEffect
    • render 메서드가 필요 없음, JSX 반환
    • 향후 React 업데이트는 함수형 컴포넌트를 대상으로 추가됨
  • children

    • 컴포넌트의 자식 요소를 의미
      • 컴포넌트 내 또 다른 컴포넌트를 포함, 텍스트를 넣을 떄 사용하는 속성
    • 리액트에서 컴포넌트를 만들 때, 그 안에 다른 컴포넌트나 요소를 넣을 수 있음
    • 컴포넌트가 자식 컴포넌트의 UI를 유연하게 구성할 수 있음
  • PropsWithChildren

    • 리액트에서 제공하는 타입 유틸리티 중 하나로
    • 컴포넌트의 props타입에 children 속성을 자동으로 추가
    • 컴포넌트를 정의할 때 children을 명시적으로 추가하지 않아도 됨
    • children이 optional로 되어 있어서 undefined 상태를 고려해서 사용할 수 있음
    • ReactNode 타입으로 정의가 되어 있는데, 특정 타입으로 사용하고 싶을 경우 children:string과 같이 명시적으로 정의할 수 있음
    • children이 중요하거나 특정 구조를 가질 때는 명시적으로 children을 정의하는 것이 가독성 면에서 좋음
    import React, { PropsWithChildren } from "react";
    
    interface CardProps {
      title: string;
    }
    
    const Card: React.FC<PropsWithChildren<CardProps>> = ({ title, children }) => {
      return (
        <div style={{ border: "5px solid #ccc", padding: "10px", margin: "10px" }}>
          <h2>{title}</h2>
          <div>{children}</div>
        </div>
      );
    };
    
    function App() {
      return (
        <div>
          <Card title="1.카드">
            <p>카드 입니다</p>
          </Card>
        </div>
      );
    }
    
    export default App;
    
    import React, { PropsWithChildren } from "react";
    
    // Container 컴포넌트 정의
    interface ContainerProps {
      backgroundColor: string;
    }
    
    const Container: React.FC<PropsWithChildren<ContainerProps>> = ({
      backgroundColor,
      children,
    }) => {
      return (
        <div style={{ backgroundColor, padding: "20px", margin: "10px" }}>
          {children}
        </div>
      );
    };
    
    // 사용 예시
    function App() {
      return (
        <div>
          <Container backgroundColor="lightblue">
            <p>이것은 첫 번째 컨테이너입니다.</p>
          </Container>
          <Container backgroundColor="lightgreen">
            <p>이것은 두 번째 컨테이너입니다.</p>
          </Container>
        </div>
      );
    }
    
    export default App;
    
  • ReactNode

    • 리액트에서 JSX로 표현될 수 있는 모든 타입
    • 기본 타입, 리액트 element(div, Component 등), 배열 및 객체, ReactPortal(다른 DOM 노드에 렌더링 될 수 있는 요소)
  • React.FunctionComponent

    • React에서 함수형 컴포넌트를 정의할 때 사용하는 타입스크립트 타입
    • props의 타입을 명시할 수 있음 : 타입 오류 사전 방지
    • children 속성을 자동으로 추가
    • defaultProps, propType, displayName과 같은 속성 지원
      • Button.displayName = “Button”
    • 단점 : children의 불필요한 포함
    • 오버 엔지니어링 : 간단한 컴포넌트에도 불필요하게 많은 것들이 들어감
      • React.FC를 사용하지 않고도 props 타입을 명시적으로 정의 가능
    • children을 꼭 사용할 예정이라면 / props 타입을 명확하게 정의하고 싶을 때 사
  • children 사용 시 주의할 점

    • 유형이 예측 불가능한 경우 : ReactNode일 경우, 여러 가지 타입이 올 수 있음, children의 형태가 통일되지 않을 경우 문제
      • 컴포넌트의 안정성을 떨어트리고, 예기치 않은 오류를 발생
    • prop drilling 문제 : 중첩된 컴포넌트들 사이에 전달할 때, 여러 단계를거쳐서 전달되는 경우
      • 코드 가독성과 유지보수성에 악영향 : context api가 대안
    • 명시적으로 예측 가능한 컴포넌트의 구조나 사용 방식을 모두 알 수 있게 문서화 필요
  • Prop-types

    • 컴포넌트가 받는 props의 데이터 타입을 정의하고 올바른 타입의 props가 전달되었는지 확인하는 검증 라이브러리
    • 잘못된 props가 전달되었다면 오류가 발생
      • ex) 문자열을 받아야 하는 props에 숫자를 전달하면 경고 발생
    • 필수 항목을 isRequired를 이용하여 지정 가능
    • 문자열, 숫자, 불리언, 함수, 객체, 배열, 엘리먼트, ReactNode, any
    • isRequired, oneof, oneoftype, arrayof, exact,…
    • 런타임에 props의 타입을 검사
    import React from 'react';
    import PropTypes from 'prop-types';
    
    const MyComponent = ({ title, age }) => {
      return (
        <div>
          <h1>{title}</h1>
          {age && <p>Age: {age}</p>}
        </div>
      );
    };
    
    // PropTypes 정의
    MyComponent.propTypes = {
      title: PropTypes.string.isRequired, // title은 필수 prop
      age: PropTypes.number, // age는 선택적 prop
    };
    
    export default MyComponent;
    
  • 변수 / 함수

    • 변경된다고 해서 다시 렌더링되지 않음
    • 변수나 함수는 컴포넌트의 UI를 직접적으로 변경하지 않음
    • 화면상의 변화와 무관