React 컴포넌트 타입인 ReactElement vs JSX.Element vs ReactNode 차이와 예시

728x90

 

 

컴포넌트의 props에 컴포넌트를 넘겨야 할 때, props의 이름과 컴포넌트의 타입을 선언해주어야 한다.

 

import { JSX, ReactElement, ReactNode, useEffect, useState } from 'react'

interface Props {
  component: ReactElement
  component1: JSX.Element
  component2: ReactNode
}

 

하지만 이 컴포넌트의 타입은 `ReactElement` , `Element` , `ReactNode` 세가지가 있으며, 세가지 모두 리액트의 요소를 나타낸다.

이 타입들의 차이는 무엇이 있을 지 알아보자.


ReactElement

리액트에서는 JSX 문법으로 UI를 표현하고, 트랜스파일러JSX문법을 createElement 메서드를 통해 리액트 엘리먼트를 생성한다.

 

📌 JSX 문법

class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}

 

📌 createElement 메서드 사용

class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}

 

리액트는 이렇게 만들어진 리액트 엘리먼트 객체를 읽어 가상 DOM을 구성한다.

이때 리액트 엘리먼트 객체의 타입이 ReactElement 이다.

 


ReactNode

ReactNode의 타입 정의 코드

 

ReactNode는 앞서 설명한 더 넓은 범주의 타입을 포함한다.

즉, ReactNode는 리액트의 render 함수가 반환할 수 있는 모든 형태를 담기고 있다고 생각하면 된다.


JSX.Element

 

JSX.Element의 타입 정의 코드

 

JSX.Element는 ReactElement의 제네릭으로 any타입을 가지도록 확장하고 있다.

JSX.Element 는 ReactElement의 특정 타입으로 props와 타입필드를 any로 가지는 타입이라는 것만 알면 된다.

 

지금껏 살펴본 세가지 타입의 포함관계를 정리하면 아래의 그림과 같다.

 

 

📌  요약 정리

타입 설명
ReactElement JSX의 createElement 메서드의 리턴타입인 엘리먼트 객체의 타입.
즉, JSX 문법을 사용하면 트랜스파일러가 createElement로 앨리먼트 객체로 트랜스파일하는데, 그 객체의 타입이다.
ReactNode React의 render 함수가 반환할 수 있는 모든 범주의 타입.
JSX.Element ReactElement의 특정 타입

 


🙌 사용예시 

그렇다면 어떤 상황에서 어떤 타입을 써야 할까?

 

ReactNode

리액트의 render 함수가 반환할 수 있는 모든 형태를 담고 있기 때문에 리액트 컴포넌트가 가질 수 있는 모든 타입을 의미한다.

리액트의 합성을 쓰기 위해 props로 children을 많이 사용했을 텐데, 이때 children의 타입도 ReactNode이다.

리액트의 내장타입인 PropsWithChildren 타입의 children의 타입은 `ReactNode` 이다.

 

즉, ReactNode는 ReactNode로 선언한 프로퍼티가 리액트 컴포넌트처럼 다양한 형태를 가지고 싶게 하고 싶을 때 , 혹은 리액트에 내장된 children의 쓰임새처럼 넓게 쓰고 싶을 때 사용한다.


JSX.Element

리액트 엘리먼트props로 전달받아 render props패턴으로 컴포넌트를 구현할 때 사용한다.

interface Props {
  icon: JSX.Element
}

const Icon = ({ icon }: Props) => {
  // props로 받은 컴포넌트의 props에 접근할 수 있다.
  const iconSize = icon.props.size
  return <li>{icon}</li>
}

const App = () => {
  return <Icon icon={<Star size={14} />} />
}

ReactElement

JSX.Element에서의 props타입을 제네릭으로 지정해줄 수 있다.

 

interface IconProps {
  size: number
}
interface Props {
  icon: ReactElement<IconProps>
}

const Icon = ({ icon }: Props) => {
  const iconSize = icon.props.size
  return <li>{icon}</li>
}

 

ReactElement를 사용하면 icon.props에 접근할 때 어떤 props가 있는지 IDE가 추론할 수 있다.

 

출처

우아한 타입 스크립트 with 리액트 - 우아한 테크

728x90
반응형