React

[React] ReactNode / ReactElement / JSX.Element 의 차이

Chae-ri🍒 2024. 6. 25. 23:59

프로젝트 태스크를 진행하다가 children 타입을 React.ReactElement; 로 두고 태스크 완성한 걸 PR에 올려두었다.

 

여기서 받은 다른 팀원 분의 질문

요기 ReactNode가 아니라 ReactElement로 타입 좁혀놓으신 이유가 있을까용?

 

이 질문을 보면서 ReactNode와 ReactElement의 차이를 제대로 설명을 할 수 있어야겠다고 생각하여 공부하면서 이 포스트에 정리해보겠다.

 

children의 타입으로 사용하는 타입에는 크게 ReactNode와 ReactElement가 있다. 

 

ReactNode

-> 클래스형 컴포넌트의 리턴값에 해당

ReactNode는 JSX에서 children으로 전달될 수 있는 모든 타입을 가질 수 있다.

string, number, boolean, null, undefined, ReactElement, ReactFragment, ReactPortal

interface ModalRendererProps {
  title: string;
  children: React.ReactNode;
}

 

보통 children을 유연하게, 범용적으로 사용하기 위해 ReactNode를 많이 쓴다.

 

ReactElement

 

-> 함수형 컴포넌트의 리턴값에 해당

ReactElement는 오직 JSX 요소만을 가질 수 있다. 즉, 자바스크립트의 원시 타입들은 가질 수 없다는 것!

type, props를 가진다.

interface ModalRendererProps {
  title: string;
  children: React.ReactElement;
}
    interface ReactElement<
        P = any,
        T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>,
    > {
        type: T;
        props: P;
        key: string | null;
    }

 

ReactElement는 createElement 함수를 통해 생성된 객체의 타입이다.

따라서 ReactElement 타입은 자식 요소로 하나의 컴포넌트를 받는 것을 강제해야 하는 상황에 사용할 수 있다!

 

그렇다면 여기서 추가적으로 JSX.Element는 JSX 요소만을 가지는 ReactElement와 무슨 차이가 있을까?

 

JSX.Element

JSX.Element는 ReactElement의 타입과 props를 모두 any로 받는다. ReactElement의 특정 타입이라고 생각하면 된다.

declare global {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> {}
  }
}

 

 

ReactNode > ReactChild > ReactElement

 

728x90