프로그래밍/React

[React, TS, MUI] 여러 컴포넌트에 일괄적으로 커스텀 스타일 적용하기

choar 2022. 9. 28. 21:55
반응형

[React, TS, MUI] 여러 컴포넌트에 일괄적으로 커스텀 스타일 적용하기

 

최근 React + TypeScript + MUI로 랜딩 페이지를 만들기 시작했다.

센드버드의 랜딩 페이지를 클론하는 것을 베이스로, 조금씩 변화를 주면서 구현하고 있다.

 

위 화면 하단의 아이콘이 일렬로 정렬된 부분을 클론하면서 MUI의 Material Icons를 사용했다.

아이콘 컴포넌트를 담는 배열을 만들었고, 컴포넌트 각각의 sx prop에 fontSize를 전달했다.

 

💡 sx prop이란?
The sx prop is a shortcut for defining custom styles that has access to the theme. (ref)
mui 컴포넌트에 커스텀 스타일을 적용할 수 있는 prop이다.
sx가 정확히 무엇의 약어인지는 모르겠지만 style extension 아닐까 추측한다 🧐

 

// BEFORE
const logoComponents: JSX.Element[] = [
  <AttachMoney sx={{ fontSize: 50 }} />, 
  <Euro sx={{ fontSize: 50 }} />, 
  <CurrencyFranc sx={{ fontSize: 50 }} />,
  <CurrencyPound sx={{ fontSize: 50 }} />, 
  <CurrencyYen sx={{ fontSize: 50 }} />,
  <CurrencyBitcoin sx={{ fontSize: 50 }} />
];

export const Logos = () => {
  return (
    <Container sx={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap' }}>
      {logoComponents.map((logo) => logo)}
    </Container>
  )
};

이렇게 구현할 경우 fontSize를 수정하려면 전부 다 직접 수정해줘야 한다는 번거로움이 있다.

배열에 아이콘을 추가할 때도 fontSize를 직접 지정해줘야 한다.

 

 

// AFTER
const IconWithFontSize = (Icon: OverridableComponent<SvgIconTypeMap<{}, "svg">>, fontSize: number) => {
  return <Icon sx={{ fontSize }} />;
};

const logoComponents: (OverridableComponent<SvgIconTypeMap<{}, "svg">>)[] = [
  AttachMoney,
  Euro, 
  CurrencyFranc, 
  CurrencyPound, 
  CurrencyYen, 
  CurrencyBitcoin
];

export const Logos = () => {
  return (
    <Container sx={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap' }}>
      {logoComponents.map((logo) => IconWithFontSize(logo, 50))}
    </Container>
  )
};

배열에 아이콘 컴포넌트가 아닌 아이콘 컴포넌트 함수를 담았고, (ex. <Something /> → Something)

IconWithFontSize라는 함수를 만들었다.

IconWithFontSize는 아이콘 컴포넌트 함수와 fontSize를 받아 fontSize 크기를 가진 아이콘 컴포넌트를 리턴한다.

이렇게 하면 map 함수에서 IconWithFontSize에 전달하는 인자만 바꿔 컴포넌트 전부의 크기를 쉽게 바꿀 수 있고, 배열에 아이콘을 추가하는 것도 간단하다.

 

간단한 문제 해결 기록 끝..!

Best practice인지는 모르겠다. 계속 공부해야지 👀

 

🌟 내용에 오류가 있다면 댓글 달아주시면 감사하겠습니다.

반응형