JSX.Element / ReactNode / ReactElement

Winney·2021년 4월 14일
5

리액트

목록 보기
2/2

Typescript를 사용하면서 가장 어렵다고 생각하는 부분이 컴포넌트나 기타 라이브러리의 타입을 어떻게 지정하는가에 대한 부분이라고 생각한다.
오늘도 React.Element를 찾다가 StackOverFlow에 좋은 답변이 있어서 정리해보려고 한다.

용어

  • 네임 스페이스 (name space) : 구분이 가능하도록 정해놓은 범위나 영역. 이름을 한 곳에 모아 충돌을 방지하고 해당 이름으로 선언된 변수는 함수를 쉽게 가져다 쓸 수 있다록 만든 메커니즘.
    ❗️ 네임 스페이스 패턴(name space pattern)을 검색하면 더 확실히 알 수 있다.

1. ReactElement

React.element는 type과 props를 가진 객체이다.

type Key = string | number

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

2. ReactNode

ReactNode는 ReactElement, ReactFragment, string, number, ReactNode의 Array, null, undefined, boolean이다.

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

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

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

3. JSX.Element

JSX.Element는 props와 type이 any인 제네릭 타입을 가진 ReactElement이다. JSX는 글로벌 네임 스페이스에 있기 때문에 다양한 라이브러리에서 자체 라이브러리의 방법대로 실행 될 수 있다.

리액트의 경우 다음과 같이 실행된다.

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

예시

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

4. Class component와 Functional component의 render 시 return 값 차이

  • Class ComponentReactNode를 return
render(): ReactNode;
  • Functional ComponentReactElement를 return
  • Functional component는 stateless components이다.
interface StatelessComponent<P = {}> {
  (props: P & { children? : ReactNode }, context?: any): ReactElement | null;
}

5. 그래서 타입 선언 시 Class component와 Functional component는 어떻게 다를까?!

✏️ Class Component는 ReactNode를 타입으로 지정한다. ReactNode는 그 자체로 다양한 타입을 지니기 때문에 충분!
✏️ Functional Component는 ReactElement는 object 형태로 null 값을 가지고 있지 않기 때문에 union을 사용해서 null 값을 줘야한다. 💯 ReactElement | null

const Example = () : ReactElement | null => {
  if(condition) {
    return null;
  };
  
  return <h1>Hello World</h1>
};
profile
프론트엔드 엔지니어

0개의 댓글