티스토리 뷰

타입스크립트로 리액트 코드를 작성하다보면 컴포넌트의 타입을 정해줘야하는데 너무 여러가지 타입이 있어서 헷갈려서 정리하고자 합니다.

 

배경지식

클래스형 컴포넌트는 render메소드에서 ReactNode를 리턴한다. 함수형 컴포넌트는 ReactElement를 리턴한다. JSX는 바벨에 의해서 React.createElement(component, props, ...children) 함수로 트랜스파일된다. html 처럼 생긴 문법을 리액트 라이브러리의 렌더링 함수로 변환하는것이다. 그래서 JSX를 사용하지 않고도 리액트를 사용할 수 있으나(JSX없이 사용하는 React) 이렇게 하면 매우 불편하다.

// jsx
<div>Hello {this.props.toWhat}</div>
<Hello toWhat="World" />

JSX는 아래 처럼 변경된다.

// transpile
React.createElement('div', null, `Hello ${this.props.toWhat}`);
React.createElement(Hello, {toWhat: 'World'}, null);

React.createElement의 리턴 타입이 바로 ReactElement와 JSX.Element이다.

포함관계

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

ReactElement

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

React.createElement를 호출하면 이런 타입의 객체가 리턴된다. 그냥 리액트 컴포넌트를 JSON 형태로 표현해놨다고 생각하자.

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;

ReactNodeReactElementsuperset이다. ReactNodeReactElement일 수 있고 null, undefined, boolean 등등.. 좀 더 유연한 타입 정의라고 할 수 있다.

JSX.Element

JSX.ElementReactElement의 특정 타입이라고 생각하자. 또한 글로벌 네임스페이스에 정의되어 있어 외부 라이브러리에서 이 JSX.Element를 재정의할 수 있다.

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

 

예시

<p> // <- ReactElement = JSX.Element
  <Custom> // <- ReactElement = JSX.Element
    {true && "test"} // <- ReactNode
  </Custom>
</p>

질문

왜 클래스형 컴포넌트의 render()는 ReactNode를 리턴하고 함수형 컴포넌트는 ReactElement를 리턴하는가?

historical reasons이라고 한다.

 

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

const example = (): ReactElement | null => {
	if(/* true조건 */) return null;
    
	return <p>Hello World</p>;
};
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함