다음은 헤더 컴포넌트의 리턴 부분이다.
LeftExtras와 RightExtras는 뒤로가기, 검색버튼, 닫기버튼 등 헤더에 추가적으로 들어갈 수 있는 ReactNode 타입의 prop인데, 방향을 제외한 렌더링 방식이 매우 유사하다.
이런 부분은 렌더함수로 분리하여 사용하면 중복코드도 줄이며 더 깔끔하게 처리할 수 있다.
// Before
return (
<StyledWrapper>
<StyledRow {...propsWithDefault} direction="left" gap={leftExtrasGap}>
{LeftExtras}
</StyledRow>
<Title />
<StyledRow {...propsWithDefault} direction="right" gap={rightExtrasGap}>
{RigthExtras}
</StyledRow>
</StyledWrapper>
);
// After
const renderExtras = (direction: 'left' | 'right') => {
const [Extras, gap] =
direction === 'left'
? [LeftExtras, leftExtrasGap]
: [RigthExtras, rightExtrasGap];
return (
<StyledRow {...propsWithDefault} direction={direction} gap={gap}>
{Extras}
</StyledRow>
);
};
return (
<StyledWrapper isVisible={isVisible}>
{renderExtras('left')}
<Title />
{renderExtras('right')}
</StyledWrapper>
);
() ⇒ void
가 아닌 이벤트 객체를 넘겨받을 수 있도록 (e?:MouseEvent) ⇒ void
이렇게 e를 optional하게 넘겨주야 정확하다.
-> The styled method works perfectly on all of your own or any third-party components, as long as they attach the passed className prop to a DOM element.
const renderIcon = (side: ButtonIconSideType) => {
const Icon = side === 'left' ? LeftIcon : RightIcon;
//인 경우 Icon에 undefined값이 들어갈수도 있다는 있다는 것을 예측하기 어려움
// 따라서 Icon & 가 읽고 이해하기 어려운 부분
return (Icon & <Icon style={getButtonIconStyle(height, side)} fill={textColor} />);
};
초기값의 의미
ex) button에 type이라는 prop이 있고, 들어갈 수 있는 타입은 'primary' | 'secondary' | 'highlight' 이다. 이때 type이 지정되지 않으면 primary 타입을 default로 지정하고 싶을 때 초기값의 의미로 디폴트 값을 사용한다.
에러 방지용
ex) 컴포넌트에서 onClick이 옵셔널 prop이라면 onClick()을 호출했을 때 오류가 나거나 onClick?.()과 같이 사용해야한다. 옵셔널 prop이 아니더라도 이는 자바스크립트 런터임에 발생할 수 있는 에러이다. 따라서 이를 방지하기 위해 디폴트 값을 () => null로 할당한다.
우선순위
ex) 지정된 type이 없다면 배경색을 흰색으로 설정한다는 의미의 우선순위가 있는 디폴트 값을 의미한다. (?? 또는 || 연산자를 사용하여 값을 할당한 경우)
컴포넌트와 컴포넌트 사이의 각각의 margin이 겹치면, collapse
→ 더 큰 마진의 공간만 차지된다. (마진+마진 x)
Storybook에서 apollo mock 데이터 사용 [링크]
apollo-client fetch policy