본문 바로가기
프론트엔드/TS 공부

ReactNode / ReactChild / ReactElement / JSX.element

by 학습하는 청년 2024. 5. 24.

최종 수정 : 2024-05-24

 

클래스형 컴포넌트는 render()에서  ReactNode를 리턴하고, 함수형 컴포넌트는 ReactElement 인터페이스를 리턴한다. 왜 그럴까? 그것은 historocal reasons이라고 한다.

historocal reasons

ReactNode 이외에는 null 타입을 가지지 않으므로 ReactElement를 리턴하는 함수형 컴포넌트에서는 아래와 같 null을 union 해줘야 한다.

const example = (): ReactElement | null => {
  if(true condition) return null;
  
  return <p>Hello World</p>;
};

포함관계

ReactElement와 JSX.Element는 묶어서 생각해도 좋다. JSX.Element의 제네릭 인터페이스가 ReactElement이다.

 

Q. JSX.Element와 ReactElement의 차이는 무엇인가?

거의 없다. JSX.Element는 ReactElement 인터페이스를 상속받은 인터페이스이다. 내부 구조나 제약 타입이 별도로 존재하지 않아 완전히 동일하다고 봐도 무방하다.

// index.d.ts
declear gobal {
  namespace JSX {
    interface Element extends React.ReactElement<any, any> { }
    ...
  }
}

 

타입별 허용 범위 비교

ReactNode > ReactChild > ReactElement

 

ReactNode 타입은 컴포넌트, 원시 타입, null, undefined를 모두 허용한다.

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

 

ReactChild 타입은 컴포넌트, 원시 타입 리터럴을 허용한다.

type ReactChild = ReactElement | ReactText;

 

ReactElement 타입은 createElement 함수를 통해 생성된 컴포넌트만을 허용한다.

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
    type: T;
    props: P;
    key: Key | null;
}

ReactElement

interface ReactElemnt<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
  type: T;
  props: P;
  key: Key | null;
}

 

React.createElement를 호출하면 이런 타입의 객체가 리턴된다. 그냥 리액트 컴포넌트를 JSON 형태로 표현해놨다고 말할 수 있다. ReactNode 와는 달리 원시 타입을 허용하지 않고 완성된 jsx 요소만을 허용한다.


ReactNode

type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

interface ReactnodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

ReactNode는 ReactElement의 superset이다. ReactNode는 ReactElement일 수 있고, null, undefined, boolean 등등 좀 더 유연한 타입 정의라고 할 수 있다. 즉, jsx 내에서 사용할 수 있는 모든 요소의 타입을 의미한다. 이런 이유에서 children 속성의 타입으로 가장 많이 사용하는 타입이기도 하다. 


참고 자료

https://velog.io/@kokoball0/TypeScript-ReactNode%EC%99%80-ReactElement

 

[TypeScript] ReactNode와 ReactElement

클래스형 컴포넌트는 render메소드에서 ReactNode를 리턴한다. 함수형 컴포넌트는 ReactElement를 리턴한다. JSX는 바벨에 의해서 React.createElement(component, props, ...children) 함수로 트랜스파일된다. htm

velog.io

https://merrily-code.tistory.com/209

 

ReactNode, ReactChild, ReactElement 타입 비교

자식 요소를 감싸는 래퍼 컴포넌트를 작성할 때 자식 요소인 children 속성의 타입을 명시해야 하는 경우가 자주 있습니다. 그런데, ReactChild, ReactElement, ReactNode 등 비슷한 이름을 갖는 타입이 너무

merrily-code.tistory.com

 

댓글