type UserProps = {
name: string;
};
const Profile: React.FC<UserProps> = ({name}) => {
<div> 안녕하세요, {name}님 <div>
);
export default Profile;
React.FC를 사용하는 경우 위와 같이 props의 타입을 Generics로 넣어서 사용한다.
우선 지난 문서이긴 하지만 CRA에서 기본 템플릿에 FC를 빼야한다는 PR이 올라왔고, 그것이 실제로 반영되었다고 한다. 그 이유는 아래와 같다.
React.FC 사용 시 props는 children을 암시적으로 가지게 된다.
이는 꼭 타입스크립트에 한정하지 않더라도 안티패턴이라고 한다.
const App: React.FC = () => {
return <div>hi</div>;
};
const Example = () => {
<App>
<div>Unwanted children</div>
</App>;
};
위에서 은 컴포넌트에서 children을 다루고 있지 않음에도 Example에서 children을 넘겨주고 있으며, 이는 런타임 에러가 발생하지 않는다.
이는 FC를 사용하지 않는다면 잡아낼 수 있다.
물론 오히려 FC를 사용해서 children을 작성하지 않아도 되는 편리함이 있을 수도 있으나 타입스크립트를 사용하는 목적에 어긋난다.
다음과 같이 제네릭 컴포넌트를 작성한다고 예를 들어보자.
type GenericComponentProps<T> = {
prop: T;
callback: (t: T) => void;
};
const GenericComponent = <T>(props: GenericComponentProps<T>) => {
/*...*/
};
그러나 이런 형태는 React.FC에서 허용되지 않는다.
const GenericComponent: React.FC</* ??? */> = <T>(props: GenericComponentProps<T>) => {/*...*/}
다음과 같이 연관성 있는 컴포넌트에 대해서 네임 스페이스 패턴을 적용하는 방법이 있다.
<Select>
<Select.Item />
</Select>
이를 FC를 사용할 때 물론 쓸 수는 있지만 매우 불편하다.
// FC를 사용할 때
const Select: React.FC<SelectProps> & { Item: React.FC<ItemProps> } = (
props
) => {
/* ... */
};
Select.Item = (props) => {
/*...*/
};
// FC를 사용하지 않을 때
const Select = (props: SelectProps) => {
/* ... */
};
Select.Item = (props: ItemProps) => {
/*...*/
};
가장 일반적이고 간단한 방법은 props 옆에 타입을 정의해주는 것이다.
const C1: React.FC<CProps> = (props) => {}; // React.FC 사용
const C2 = (props: CProps) => {}; // 미사용