[React]React.FC 사용 지양해야하는 이유

김건휘·2024년 8월 22일
0

React

목록 보기
7/19
post-thumbnail

리액트 관련 아티클을 읽거나 강의를 보다면 React.FC를 사용하는 것을 자주 목격할 수 있다.(특히, 오래된 아티클이나 강의)React.FC가 무엇인지 알아보고, 지양해야하는 이유에 대해서 알아보자

📌React.FC란?

React.FC (React Functional Component)는 React에서 함수형 컴포넌트를 정의할 때 사용하는 TypeScript 타입입니다.

📌React.FC의 역할?

  1. 프롭스 타입 안전성 제공
  2. 기본 props 및 children 지원 : React.FC는 기본적으로 children 프롭스를 포함시켜, 컴포넌트에 자식 요소를 전달할 수 있게 한다. 또한 기본 프롭스(defaultProps) 처리도 가능하게 합니다.
  3. 명시적 반환 타입

📌React.FC의 장점

children 프롭스를 자동으로 포함한다

import React from 'react';

const Box: React.FC = ({ children }) => {
  return (
    <div style={{ border: '1px solid black', padding: '10px' }}>
      {children}
    </div>
  );
};

const App: React.FC = () => {
  return (
    <Box>
      <p>This is inside the Box component!</p>
    </Box>
  );
};

export default App;

위 예시에서 Box 컴포넌트는 React.FC를 사용하기 때문에 children을 자동으로 프롭스로 받을 수 있다. 따라서 App 컴포넌트에서 Box 안에

태그를 넣으면, 이 내용이 Box 컴포넌트 내부에 렌더링됩니다.

타입 안전성을 제공

  import React from 'react';

interface ButtonProps {
  label: string;
  onClick: () => void;
}

const Button: React.FC<ButtonProps> = ({ label, onClick }) => {
  return (
    <button onClick={onClick}>
      {label}
    </button>
  );
};

const App: React.FC = () => {
  return (
    <Button
      label="Click Me"
      onClick={() => alert('Button clicked!')}
    />
  );
};

export default App;

이 예시에서 Button 컴포넌트는 label이라는 string 타입의 props와 onClick이라는 함수 타입의 프롭스를 받도록 React.FC<ButtonProps>를 사용해 정의했다. 이로 인해, App 컴포넌트에서 Button에 잘못된 타입의 프롭스를 전달하려고 하면 컴파일 타임에 오류가 발생한다.

그런데 왜 React.FC 사용을 지양해야 할까??

📌React.FC 사용을 지양해야 하는 이유

1. children을 암시적으로 가지고 있다.

React.FC를 사용하면 children 프롭스가 자동으로 포함된다. 하지만 모든 컴포넌트가 children을 필요로 하는 것은 아니다. 따라서, 컴포넌트가 children을 사용하지 않는데도 불구하고 불필요하게 children 프롭스가 포함되는 것은 혼란을 야기할 수 있다는 것. 장점이 단점이 될 수 있다.

예를 들어, children이 필요 없는 단순한 버튼 컴포넌트의 경우:

interface ButtonProps {
  label: string;
}

const Button: React.FC<ButtonProps> = ({ label }) => {
  return <button>{label}</button>;
};

이런 경우에도 children이 기본으로 포함되기 때문에, 실수로 children을 전달하는 등의 문제가 발생할 수 있다.

2. 타입스크립트의 제네릭 문법을 지원하지 않는다.

3. 기본적으로 반환 타입이 JSX.Element | null로 고정.

React.FC는 컴포넌트의 반환 타입을 JSX.Element | null로 고정한다. 이는 유연성을 제한할 수 있다. 예를 들어, 일부 컴포넌트는 특정 조건에 따라 undefined를 반환할 수 있지만, React.FC를 사용하면 undefined는 허용되지 않는다.

const MyComponent: React.FC = () => {
  if (someCondition) {
    return null; // null은 허용
  }
  return undefined; // 오류 발생
};

4. 디폴트 프롭스(defaultProps) 사용의 제한.

TypeScript에서 defaultProps와 React.FC를 함께 사용할 때 문제가 발생할 수 있다. React.FC는 기본적으로 defaultProps를 잘 처리하지 않아서, 명시적인 타입 정의나 다른 방법이 필요합니다. 이 때문에 defaultProps를 사용하려면 번거로움이 생긴다.

interface MyComponentProps {
  label?: string;
}

const MyComponent: React.FC<MyComponentProps> = ({ label = "Default" }) => {
  return <div>{label}</div>;
};

MyComponent.defaultProps = {
  label: "Default",
}; // 타입 문제 발생

5. 명시적 타입 정의 선호.

많은 개발자들은 코드의 명확성과 유연성을 위해 React.FC를 사용하지 않고, 명시적으로 프롭스 타입과 반환 타입을 정의하는 것을 선호한다. 이렇게 하면 불필요한 children 프롭스를 포함하지 않으며, 반환 타입도 자유롭게 조정할 수 있다.


결론

가장 일반적이고 간단한 방법인 props 옆에 타입을 정의해주자.

const R1: React.FC<RProps> = (props) => {}; // React.FC 사용
const R2 = (props: RProps) => {}; // 미사용
profile
공유할 때 행복을 느끼는 프론트엔드 개발자

0개의 댓글