리액트는 HTML5의 각 태그에 대응하는 리액트 컴포넌트를 제공한다.
const h1 = <h1>Hello</h1>
이를 React.createElement
함수로 표현하면 다음과 같다.
const h1 = React.createElement('h1', null, "Hello")
리액트 컴포넌트의 이름은 소문자로 시작한다.
리액트가 컴포넌트를 이런 방식으로 설계한 것은 HTML5에 해당하는 컴포넌트 이름을 일일이 임포트하지 않게 하려는 의도이다.
import {h1, h2, div} from 'react'
아래의 JSXVirtualDOM
은 사용자 컴포넌트이다.
리액트 컴포넌트 또는 다른 사용자 컴포넌트의 조합으로 이루어진다.
const JSXVirtualDOM = (
<ul>
<li>
<a href="https://www.google.com" target="_blank">
<p>구글로 이동</p>
</a>
</li>
</ul>
)
앞의 포스팅에서 React.createElement
의 함수 선언문을 봤었다.
다시 가져와보자.
function createElement<P extends {}>(
type: FunctionComponent<P> | ComponentClass<P> | string,
props?: Attributes & P | null,
...children: ReactNode[]): ReactElement<P>;
매개변수 type
의 타입이 string
일 수도 있지만 FunctionComponent<P>
또는ComponentClass<P>
타입일 수도 있다.
함수형 컴포넌트의 타입이 FunctionComponent<P>
이고 클래스 컴포넌트의 타입이 ComponentClass<P>
이다.
리액트에서 클래스 컴포넌트는 반드시 react패키지가 제공하는 Component
클래스를 상속해야 한다.
그리고 render
라는 이름의 메서드를 포함해야한다.
render
메서드는 React.ReactNode
타입을 리턴해야 한다.
// 기본형
import React, {Component} from 'react'
class ClassComponent extends Component {
render(): React.ReactNode {
return null
}
}
// JSX형
import React, {Component} from 'react'
class ClassComponent extends Component {
render(): React.ReactNode {
return (
<ul>
<li>
<a href="https://www.google.com" target="_blank">
<p>구글로 이동</p>
</a>
</li>
</ul>
)
}
}
import React, {Component} from 'react'
type ClassComponentProps = {
href: string;
text: string;
}
class ClassComponent extends Component<ClassComponentProps> {
render(): React.ReactNode {
const {href, text} = this.props
return (
<ul>
<li>
<a href={href} target="_blank">
<p>{text}</p>
</a>
</li>
</ul>
)
}
}
// 컴포넌트 호출
<ClassComponent href='https://google.com' text="구글로 이동" />
앞의 클래스 컴포넌트는 render
만 의미가 있고 나머지 코드는 render
메서드를 구현할 수 있게 하는 프로그래밍 언어의 문법을 갖추는 코드일 뿐이다.
리액트 개발팀은 이에 주목하여 클래스 컴포넌트의 render
메서드 부분을 간단히 함수로 만들 수 있게 했고, 이런 방식을 함수형 컴포넌트라고 이름 붙였다.
타입스크립트에서 함수를 만드는 구문은 2가지이다.
하나는 function 키워드로 만드는 함수이고 나머지 하나는 화살표 함수이다.
function FunctionComponent() {
return <h1>function component</h1>
}
const FunctionComponent = () => {
return <h1>function component</h1>
}
타입스크립트
import type
구문
다음 코드에서FC
타입은import type
구문을 사용했지만, Component 클래스는 단순히import
구문을 사용하고 있다.import type {FC} from 'react' import {Component} from 'react'
타입스크립트에서 타입은 컴파일할 때만 필요한 정보이다.
자바스크립트로 컴파일 될 때 사라진다.
런타임때 접근할 수 있는 게 아니다.
하지만 클래스는 물리적으로 동작하는 메서드와 속성이 있으므로 컴파일되어도 자바스크립트에 남아있다.
따라서 앞 코드에서FC
는 컴파일 되면 완전히 사라지는 정보라서import type
구문을 사용한다.
앞서 함수 컴포넌트의 타입이 FunctionComponent<P>
라고 했다.
그런데 이름이 너무 길어서 리액트는 이를 짧게 줄인 FC
라는 이름의 타입을 제공한다.
결국 함수 컴포넌트의 타입은 FC<P>
타입이다.
FC<P>
에서P
는 Property를 의미한다.
type FunctionComponentProps = {
href: string
text: string
}
function FunctionComponent(props: FunctionComponentProps) {
const {href, text} = props
return (
<ul>
<li>
<a href={href} target="_blank">
<p>{text}</p>
</a>
</li>
</ul>
)
}
// 컴포넌트 호출
<FunctionComponent href="https://google.com" text="구글로 이동" />
import type {FC} from 'react'
type FunctionComponentProps = {
href: string
text: string
}
const FunctionComponent: FC<FunctionComponentProps> = (props) => {
const {href, text} = props
return (
<ul>
<li>
<a href={href} target="_blank">
<p>{text}</p>
</a>
</li>
</ul>
)
}
// 컴포넌트 호출
<FunctionComponent href="https://google.com" text="구글로 이동" />