괜찮은가? - children의 관점에서..

현재 회사에서 리액트로 작업 중인 프로젝트는 타입스크립트를 사용하고 있고 컴포넌트를 React.FC로 타입을 선언해 사용하고 있다.

거의 최근까지는 그냥 다른 사람이 사용하길래 컨벤션을 맞추기 위해 사용한 경향이 있었고, children을 prop으로 선언하지 않아도 이미 타입 자체에 내재되어있어 굉장히 편하다는 생각으로 모든 컴포넌트를 FC로 선언했었다.

하지만 타입스크립트를 처음에 접했을 때 봤던 '왜 React.FC사용을 지양해야하는가' 라는 내용의 아티클들이 생각났고, 최근 ReactNode, Element들에 대해 이해하기 시작하면서 children 사용 관점에서 그 이유가 정리되었다.


1. React.FC는 무엇인가?

FunctionalComponent이다.
React.FC<P> 이든 React.FunctionalComponent<p> 이든 동일하다.

함수형으로 작성한 컴포넌트 함수 자체를 React.FC라는 타입으로 선언한 것이다.
이 컴포넌트를 다른 곳에서 import하여 타입을 정해주어야할 때 ReactNode, ReactElement와 같은 것들이 아니었다. React.FC 이 자체가 해당 컴포넌트의 타입이다.

interface ITab {
  defaultTab?: number
  onClick?: () => void
  tabHeaders: number[] | string[] | React.ReactElement
  divider?: React.ReactNode
  HeaderComponent?: React.FC
}

return 반환부에서 HeaderComponent를 다양한 디자인, 기능을 가질 수 있도로 HeaderComponent를 prop으로 받아오는 부분이다. 이 때 React.FC로 타입을 선언, 또는 typeof React.Component, import해오는 컴포넌트의 형식에 맞춰 ()=>React.Element와 같이 선언하게 되는데, 맨 마지막 함수형으로 타입을 선언한 것은 내부 프롭이 달라지는 경우가 있어 거의 사용하는 의미가 없는 것으로 생각된다.


2. React.FC의 children은 ReactNode이다.

ReactFC는 자동으로 children을 prop으로 내재하고 있는 상태인데
이 때의 children 타입은 ReactNode이다.

    type PropsWithChildren<P> = P & { children?: ReactNode | undefined };

디자인패턴을 적용하면서 아토믹/컴포넌트 단위의 개발물들이 많았고 그 때는 아토믹들을 element, string이든 children으로 받아내 사용성을 높일 수 있어야 한다고 생각했다. 그래서 아토믹단위에서의 React.FC 사용은 element, string 등 폭넓게 포함하는 ReactNode로서 children을 정의해주는 것이 적합했다고 생각한다.

하지만 모든 컴포넌트들이 유용하게 쓰일 필요는 없다.
예를들면 날짜 표기 방식을 유용하게 변경해주는 DateText라는 아토믹이 있었는데, 이 아토믹은 굳이 element를 받을 필요가 없다. 날짜를 표기한 string, 또는 Date객체, Moment를 받기만 하면되고 그것이 유효한 결과값을 얻는 방법이다.
때문에 이와 같은 경우엔 굳이 React.FC를 사용할 필요가 없고 직접 children타입을 정해주는 것이 좋다.

interface IDateText extends IBasicText{
  format?: string
  children: string | Date | Moment
}

children에 무엇이든 들어와 잘못된 결과를 내지않도록 사전에 막아주고
사용자로서는 어떤 데이터를 입력해야하는지 구체적인 지침이 된다.

( 위와 유사하게 ReactFC로 선언된 중, React.isValidElement(children)으로 유효성을 체크하는 로직에서 children으로 전달한 string이 element가 아니어서 문제를 겪은 일도 있었다. )


짧게 정리하면...

children입장에서만 ReactFC를 보았다.
즉 편하다고 children을 무분별하게 받아들이지 말고
정확한 데이터 타입을 명시해줄 것!

children으로 ReactNode를 받아야하는 필요한 상황에서만 ReactFC를 사용해야겠다. 만약 컨벤션을 맞춰야한다는 강박(?)이 있다면 FC대신 PropsWithChildren<P>을 써보는 것도 좋다.

좋은 웹페이지 즐겨찾기