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
tsTry
interfaceReactElement <P = any,T extends string |JSXElementConstructor <any> = string |JSXElementConstructor <any>,> {type :T ;props :P ;key : string | null;}typeJSXElementConstructor <P > =| ((props :P ) =>ReactNode ) // Function Component| (new (props :P ) =>Component <any, any>); // Class Component
tsTry
interfaceReactElement <P = any,T extends string |JSXElementConstructor <any> = string |JSXElementConstructor <any>,> {type :T ;props :P ;key : string | null;}typeJSXElementConstructor <P > =| ((props :P ) =>ReactNode ) // Function Component| (new (props :P ) =>Component <any, any>); // Class Component
ReactElement
: JSX로 생성된 리액트 Element 객체 타입
JSX.Element
tsTry
declareglobal {/*** @deprecated Use `React.JSX` instead of the global `JSX` namespace.*/namespaceJSX {interfaceElement extendsReact .ReactElement <any, any> {}interfaceElementClass extendsReact .Component <any> {render ():React .ReactNode ;}}}
tsTry
declareglobal {/*** @deprecated Use `React.JSX` instead of the global `JSX` namespace.*/namespaceJSX {interfaceElement extendsReact .ReactElement <any, any> {}interfaceElementClass extendsReact .Component <any> {render ():React .ReactNode ;}}}
JSX.Element
: JSX 코드로 생성된 객체 타입
JSX
는 프레임워크와 무관한 문법으로 프레임워크 마다 다르게 구현된다.
리액트에서는 JSX.Element
를 ReactElement<any, any>
로 정의함
ReactNode
tsTry
typeReactNode =|ReactElement | string| number|Iterable <ReactNode >|ReactPortal | boolean| null| undefined|DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES [keyofDO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES ];
tsTry
typeReactNode =|ReactElement | string| number|Iterable <ReactNode >|ReactPortal | boolean| null| undefined|DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES [keyofDO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES ];
ReactNode
는 리액트가 렌더링할 수 있는 모든 것을 의미한다.
<div> // <- ReactElement
<Component> // <- ReactElement
{condition && 'text'} // <- ReactNode
</Component>
</div>
- 클래스 컴포넌트
render
메서드의 리턴 타입도ReactNode
children
prop도ReactNode
React Children
ReactNode
인 children
은 다양한 타입을 가질 수 있다.
즉 배열이 아닌 경우들이 존재하고,
이를 처리하기 위해 React.Children
API를 제공한다.
Children
은 타입이 아니므로 임포트할 때 type 키워드로 임포트하지 않도록 주의하자.
tsxTry
import {Children ,ReactNode } from "react";functionReversedList ({children }: {children :ReactNode }) {constresult =Children .toArray (children );result .reverse ();returnresult ;}export default functionApp () {return (<ReversedList ><p >This is the first item.</p ><p >This is the second item.</p ><p >This is the third item.</p ></ReversedList >);}
tsxTry
import {Children ,ReactNode } from "react";functionReversedList ({children }: {children :ReactNode }) {constresult =Children .toArray (children );result .reverse ();returnresult ;}export default functionApp () {return (<ReversedList ><p >This is the first item.</p ><p >This is the second item.</p ><p >This is the third item.</p ></ReversedList >);}
StyledComponent $ prefix
$ prefix 를 붙이면 DOM에 전달되지 않고 styled-components
가 스타일 조작에만 사용하게 된다.
- 스타일 조작을 위한 props를 명확하게 구분 가능
- DOM에 전달되지 않아서 불필요한 속성이 렌더링되지 않음, 이로 인한 에러를 방지 가능