오늘은 2장의 1,2 섹션을 읽고 느낀점과 탐구하고자 했던 것을 포스팅하고자 합니다.
📌 JSXElement는 createElement의 문법적 설탕?
이전에 리액트를 공부하면서 JSXElement
는 createElement
의 문법적 설탕이다. 라는 이야기를 들어본적이 있습니다.
jsx 문법을 사용해서 리턴문을 쓰면 결국 바벨이 돌아갈 때, createElement를 통해서 ReactNode
로 다시 트랜스파일링 된다는 것이었는데요.
리액트 딥다이브에서는 아래와 같은 예시가 책에 나와있습니다.
import React from 'react';
import { PropsWithChildren, createElement} from 'react';
function TextOrHeading({
isHeading,
children
}: PropsWithChildren<{isHeading: boolean}>) {
return isHeading ? (
<h1 className="text">{children}</h1>
) : (
<span className="text">{children}</span>
)
}
function TextOrHeading2({
isHeading,
children
}: PropsWithChildren<{isHeading: boolean}>){
return createElement(
isHeading ? 'h1' : 'span',
{ className: 'text'},
children,
)
}
TextOrHeading2
가 바벨로 트랜스파일링된다면 아래와 같습니다.
function TextOrHeading2({
isHeading,
children
}) {
return createElement(isHeading ? 'h1' : 'span', {
className: 'text'
}, children);
}
따라서 createElement
를 사용한다면 바벨로 트랜스파일링 되어도 타입이 제거되는 것 이외에는 별다른 차이가 없는 것을 알 수 있습니다. 따라서, 트랜스파일링의 비용도 적어질 수 밖에 없을 것 같은.. 그런 저의 추측을 해봅니다.🧐 (따라서 필요에 따라 createElement를 사용하는 것이 효율적이다..)
jsx는 결국 createElement
를 사용해서 트랜스파일링 되는데, 내부 구조 순서는 아래와 같이 적어줄 수 있습니다.
JSXchildren > JSXattributes > JSXstring
순서대로 적어주면 됩니다.
예제를 통해서 PropsWithChildren
타입에 제네릭을 넣어줄 수 있다는 걸 처음 알게 되었습니다.
type PropsWithChildren<P = unknown> = P & { children?: ReactNode | undefined };
제네릭으로 P
타입을 넣어주면 P타입과 함께 children
타입이 같이 타입이 명시되는 것을 알 수 있었습니다.
또한 저는 index.d.ts
에서 ReactFragment
타입을 열심히 찾아 다녔었는데요.
ReactNode
타입을 확인하고, ReactFragment
타입에 대한 명시도 바뀌게 되었다는 것을 알게 되었습니다.
이전에는 ReactFragment
로 명시하였었는데, 아래와 같이 변경되었습니다.
type ReactNode =
| ReactElement
| string
| number
| Iterable<ReactNode> // ReactFragment
...
위와 같이 ReactFragment
가 Iterable<ReactNode>
로 타입이 기입되고 있다는 것을 알게 되었습니다.
아래는 실제 index.d.ts
에서 정의된 ReactFragment
타입입니다.
type ReactFragment = Iterable<ReactNode>;
- 결론
- 결론적으로, JSX문법만 사용하기 보다는
createElement
를 사용하면 효율적일 수 있다를 알 수 있었습니다.
- 결론적으로, JSX문법만 사용하기 보다는