파크로그
Published 2022. 9. 7. 22:07
React Children Frontend/⚛ React

보통 children 의 type 은 ReactNode 로 설정하는 편이다.

 

children 을 배열로 사용할 상황이 있었다.

props 를 통해 받은 값을 바탕으로 Group 의 최대 갯수를 지정하고, slice 하고싶었다.

물론 group 이라는 컴포넌트에 미리 데이터를 slice 하여 보내줄 수도 있겠지만,

미리 데이터를 정제하여 보내는 것 보다 생략해서 보여주는 로직은 Group 컴포넌트의 역할이 맞다고 생각했다.

 

 

간단히 JS 환경에서 테스트해보았을 땐 children 이 배열로 반환되어서 map 을 사용할 수 있을거라고 생각하고 사용해보았다.

그런데 다음과 같은 ts 오류가 발생했다.

 

 

children 을 ReactNode 로 타입을 지정하여 사용하고 있기 때문에 오류가 났다.

의도한대로 map 메서드를 쓰고싶으면 어떻게 해야할까?

 

해결만 하고자 한다면 간단히 해결할 수도 있다. children 의 타입을 ReactNode 가 아닌 ReactNode[] 로 사용하면 된다.

 

 

그런데 이게 과연 React 에서 의도한바가 맞을까?

 

avatars 를 받고있는 children 자체가 배열이라고 판단이 되는데, ReactNode 로 도 배열형태 그대로 사용할 수 있으며, 다만 slice, map 과 같이 배열 관련된 메서드를 사용하지 못할 뿐 ReactNode 는 Iterable 한 타입을 대응할 수 있다. ReactFragment 타입이 ReactNode 의 Iterable 이기 때문이다.

 

 

또한 18 버전 변경 이전에 React.FC 타입을 사용하는 것은 children 타입을 PropsWithChildren 을 통해 ReactNode 로 사용하고 있었으며, 18 버전 부터는 children 의 타입을 명시해주도록 변경하였는데, Props 에 일일이 children 을 명시하는 것을 피하기 위해

제공하는 PropsWithChildren 타입은 children 을 ReactNode 로 명시하고 있다.

그렇기 때문에 children 을 ReactNode[] 로 사용하는 것은 의도에 벗어난다고 생각이 들었다.

 

 

그러면 Children 의 배열을 slice 하고 싶다면 어떻게 해야할까?

 

React 에서는 관련해서 Children 을 제공한다. map, forEach, count, only, toArray 등의 함수를 제공한다.

나는 children 을 slice 하고자 하므로 toArray 함수를 사용했다.

 

또한 total (children.length)을 count 함수를 통해 기본값으로 지정하였다.

 

type AvatarGropProps = {
  children: ReactNode;
  max?: number;
  total?: number;
};

const AvatarGroup: React.FC<AvatarGropProps> = (props) => {
  const {
    children: childrenProp,
    max = 5,
    total = Children.count(childrenProp),
  } = props;

  const children = Children.toArray(childrenProp);

  return <div>{children.slice(0, max)}</div>;
};

export default AvatarGroup;

 

toArray 함수는 children 을 flatten 하는 작업도 거치는데, 관련하여 어떻게 활용해볼 수 있을지 참고할만한 글 도 있어 공유한다.

 

해당 부분을 찾아보면서 ReactNode 와 ReactElement 의 차이를 명확히 볼 수있어서 좋았다.

profile

파크로그

@파크park

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!