React.FC는 React의 Functional Component를 Typescript로 개발을 할 때 사용하는 타입이다.
함수형 컴포넌트를 사용할 때 타입 선언에 사용할 수 있도록 React에서 제공하는 타입이다.
React.FC 타입은 컴포넌트에 대한 타입 정의를 제공하고, props
와 반환 타입을 안전하게 관리할 수 있다.
간단한 예제를 보자.
import React from 'react';
// props 타입 정의
interface MyComponentProps {
title: string;
onClick: () => void;
}
// React.FC를 사용하여 함수 컴포넌트의 타입을 정의
const MyComponent: React.FC<MyComponentProps> = ({ title, onClick }) => {
return (
<div>
<h1>{title}</h1>
<button onClick={onClick}>Click me</button>
</div>
);
};
export default MyComponent;
위 코드에서 MyComponentProps
인터페이스는 컴포넌트의 props 타입을 정의한다.
그리고 MyComponent
함수 컴포넌트는 React.FC 를 사용하여 MyComponentProps
타입의 props를 받는 것으로 정의되어 있다.
React.FC는 자동으로 children prop
을 포함하는데 이는 모든 컴포넌트가 children
을 받을 것이라는 잘못된 가정을 만들 수 있다.
실제로 chilren
을 받지 않아야 하는 컴포넌트에서도 children
을 받을 수 있게 된다.
이것은 타입 안정성을 저하시킬 수도 있다.
children prop
이 자동으로 포함되는 예제// React.FC를 사용하는 경우
const ComponentWithFC: React.FC = ({ children }) => {
return <div>{children}</div>;
};
// children을 받지 않아야 하는 컴포넌트에도 children을 받을 수 있음
<ComponentWithFC>Unexpected children</ComponentWithFC>
children
을 제외한 예제// React.FC를 사용하지 않는 경우
interface Props {
// 다른 props 정의
}
const ComponentWithoutFC = ({ /* 다른 props */ }: Props) => {
// children prop을 받지 않음
return <div>No children here</div>;
};
// 이 컴포넌트는 children을 받지 않으므로, 아래와 같이 사용할 수 없음
<ComponentWithoutFC>Unexpected children</ComponentWithoutFC> // 오류 발생
React.FC를 사용하면 defaultProps
가 제대로 작동하지 않던 이슈가 있었다.
defaultProps
가 React.FC에 제대로 작동되지 않던 예제// React.FC를 사용하는 경우
interface Props {
myProp?: string;
}
const ComponentWithFC: React.FC<Props> = ({ myProp }) => {
return <div>{myProp}</div>;
};
ComponentWithFC.defaultProps = {
myProp: 'Default Value',
};
// defaultProps가 예상대로 작동하지 않을 수 있음
defaultProps
를 사용하는 예제// React.FC를 사용하지 않는 경우
interface Props {
myProp: string;
}
const ComponentWithoutFC = ({ myProp = 'Default Value' }: Props) => {
return <div>{myProp}</div>;
};
// defaultProps가 함수 파라미터 기본값으로 대체됨
React.FC를 사용할 때 Generic
타입을 컴포넌트에 적용하는 것이 더 복잡해질 수 있다.
함수형 선언에서는 Generic
을 더 사용하기 쉽고 직관적으로 만들 수 있다.
Generic
컴포넌트를 만드는 예제// React.FC를 사용하는 경우
interface Props<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
const ListWithFC: React.FC<Props<any>> = ({ items, renderItem }) => (
<div>{items.map(renderItem)}</div>
);
// 제네릭을 사용하는 것이 더 복잡해짐
Generic
컴포넌트를 만드는 예제// React.FC를 사용하지 않는 경우
interface Props<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
const ListWithoutFC = <T extends {}>({ items, renderItem }: Props<T>) => (
<div>{items.map(renderItem)}</div>
);
// 제네릭 사용이 더 간단하고 직관적임
React.FC 타입은 함수 오버로딩을 지원하지 않는다.
함수 컴포넌트에서 오버로딩을 사용하려면 일반 함수 선언을 사용해야 한다.
// React.FC를 사용하는 경우
interface Props {
value: string;
}
// React.FC는 오버로딩을 지원하지 않음
const ComponentWithFC: React.FC<Props> = ({ value }) => {
return <div>{value}</div>;
};
// 함수 오버로딩을 시도할 수 없음
// React.FC를 사용하지 않는 경우
interface BaseProps {
baseValue: number;
}
function ComponentWithoutFC({ baseValue }: BaseProps): JSX.Element;
function ComponentWithoutFC({ baseValue, extraValue }: BaseProps & { extraValue: string }): JSX.Element;
function ComponentWithoutFC({ baseValue, extraValue }: BaseProps & { extraValue?: string }): JSX.Element {
if (extraValue) {
return <div>{`Base: ${baseValue}, Extra: ${extraValue}`}</div>;
}
return <div>{`Base: ${baseValue}`}</div>;
}
// 함수 오버로딩이 가능함
위 같은 이유들로 많은 타입스크립트 사용자들은 컴포넌트를 정의할 때 React.FC 대신 props
자체에 명시적인 함수 반환 타입을 사용하는 것을 선호한다.
결과적으로는 Typescript와 React를 함께 사용할 때 더 명확하고 유연한 코드를 작성하기 위해 React.FC
사용을 피하는 것이 좋다.
interface MyComponentProps {
// props 타입 정의
}
const MyComponent = ({ /* props */ }: MyComponentProps): JSX.Element => {
// 컴포넌트 구현
}