Skip to content
  • Jan
  • Feb
  • Mar
  • Apr
  • May
  • Jun
  • Jul
  • Aug
  • Sep
  • Oct
  • Nov
  • Dec
  • Sun
  • Mon
  • Tue
  • Wed
  • Thu
  • Fri
  • Sat

2024-07-01

Published:

React Component Type

JSX 코드는 트랜스파일링을 거쳐서 type, props, key 프로퍼티를 갖는 객체로 변환된다.

https://babeljs.io/docs/babel-plugin-transform-react-jsx

정확히는 JSX 코드가 createElement, jsx 함수 호출로 변환된다.

그 결과로 반환된 객체가 ReactElement 타입이다.

트랜스파일 전

const profile = (
  <div>
    <img src="avatar.png" className="profile" />
    <h3>{[user.firstName, user.lastName].join(" ")}</h3>
  </div>
);

트랜스파일 후

import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";

const profile = _jsxs("div", {
  children: [
    _jsx("img", {
      src: "avatar.png",
      className: "profile",
    }),
    _jsx("h3", {
      children: [user.firstName, user.lastName].join(" "),
    }),
  ],
});

혹은

const profile = React.createElement(
  "div",
  null,
  React.createElement("img", { src: "avatar.png", className: "profile" }),
  React.createElement("h3", null, [user.firstName, user.lastName].join(" "))
);

ReactElement

ts
interface ReactElement<
P = any,
T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>,
> {
type: T;
props: P;
key: string | null;
}
 
type JSXElementConstructor<P> =
| ((props: P) => ReactNode) // Function Component
| (new (props: P) => Component<any, any>); // Class Component
Try
ts
interface ReactElement<
P = any,
T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>,
> {
type: T;
props: P;
key: string | null;
}
 
type JSXElementConstructor<P> =
| ((props: P) => ReactNode) // Function Component
| (new (props: P) => Component<any, any>); // Class Component
Try

ReactElement: JSX로 생성된 리액트 Element 객체 타입

JSX.Element

ts
declare global {
/**
* @deprecated Use `React.JSX` instead of the global `JSX` namespace.
*/
namespace JSX {
interface Element extends React.ReactElement<any, any> {}
interface ElementClass extends React.Component<any> {
render(): React.ReactNode;
}
}
}
Try
ts
declare global {
/**
* @deprecated Use `React.JSX` instead of the global `JSX` namespace.
*/
namespace JSX {
interface Element extends React.ReactElement<any, any> {}
interface ElementClass extends React.Component<any> {
render(): React.ReactNode;
}
}
}
Try

JSX.Element: JSX 코드로 생성된 객체 타입

JSX는 프레임워크와 무관한 문법으로 프레임워크 마다 다르게 구현된다.

리액트에서는 JSX.ElementReactElement<any, any>로 정의함

ReactNode

ts
type ReactNode =
| ReactElement
| string
| number
| Iterable<ReactNode>
| ReactPortal
| boolean
| null
| undefined
| DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES];
Try
ts
type ReactNode =
| ReactElement
| string
| number
| Iterable<ReactNode>
| ReactPortal
| boolean
| null
| undefined
| DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES];
Try

ReactNode는 리액트가 렌더링할 수 있는 모든 것을 의미한다.

<div> // <- ReactElement
  <Component> // <- ReactElement
    {condition && 'text'} // <- ReactNode
  </Component>
</div>

React Children

ReactNodechildren은 다양한 타입을 가질 수 있다.

즉 배열이 아닌 경우들이 존재하고,

이를 처리하기 위해 React.Children API를 제공한다.

Children은 타입이 아니므로 임포트할 때 type 키워드로 임포트하지 않도록 주의하자.

tsx
import { Children, ReactNode } from "react";
 
function ReversedList({ children }: { children: ReactNode }) {
const result = Children.toArray(children);
result.reverse();
return result;
}
 
export default function App() {
return (
<ReversedList>
<p>This is the first item.</p>
<p>This is the second item.</p>
<p>This is the third item.</p>
</ReversedList>
);
}
Try
tsx
import { Children, ReactNode } from "react";
 
function ReversedList({ children }: { children: ReactNode }) {
const result = Children.toArray(children);
result.reverse();
return result;
}
 
export default function App() {
return (
<ReversedList>
<p>This is the first item.</p>
<p>This is the second item.</p>
<p>This is the third item.</p>
</ReversedList>
);
}
Try

inverted || reversed

StyledComponent $ prefix

$ prefix 를 붙이면 DOM에 전달되지 않고 styled-components 가 스타일 조작에만 사용하게 된다.