
컴포넌트의 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는 리액트의 render 함수가 반환할 수 있는 모든 형태를 담기고 있다고 생각하면 된다.
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 리액트 - 우아한 테크
'🌳Frontend > react' 카테고리의 다른 글
React에서 Error boundary (에러 바운더리) 를 쓰는 이유 (0) | 2025.01.11 |
---|---|
React에서 state를 정의할 때 고려해야 할 점 (feat. SSOT) (0) | 2024.02.25 |
Next.js에서 Firebase 파이어베이스로 구글 로그인 기능 구현 (0) | 2023.10.14 |
Next.js 와 파이어베이스(Firebase) 연동하기 (0) | 2023.10.14 |
Next.js 환경에서 CSS in JS Styled-Component의 치명적인 단점 (0) | 2023.10.14 |

컴포넌트의 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는 리액트의 render 함수가 반환할 수 있는 모든 형태를 담기고 있다고 생각하면 된다.
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 리액트 - 우아한 테크
'🌳Frontend > react' 카테고리의 다른 글
React에서 Error boundary (에러 바운더리) 를 쓰는 이유 (0) | 2025.01.11 |
---|---|
React에서 state를 정의할 때 고려해야 할 점 (feat. SSOT) (0) | 2024.02.25 |
Next.js에서 Firebase 파이어베이스로 구글 로그인 기능 구현 (0) | 2023.10.14 |
Next.js 와 파이어베이스(Firebase) 연동하기 (0) | 2023.10.14 |
Next.js 환경에서 CSS in JS Styled-Component의 치명적인 단점 (0) | 2023.10.14 |