React) emotion으로 theme 적용하기(type error 해결하기)

2ast·2022년 10월 18일
1
post-custom-banner

theme를 적용해보자

이미 styled component를 사용해 화면 테마를 설정한 경험이 있기 때문에 emotion도 쉽게 설정할 수 있을 줄 알았다. 실제로 찾아본 theme 적용방법도 완전히 동일했기 때문에 냉큼 시도해봤다.

const App = () => {
  
  return (
      <ThemeProvider theme={theme}>
          <Home />
      </ThemeProvider>
  );
};

이렇게 루트 컴포넌트를 ThemeProvider로 감싸고 사용할 theme을 주기만 하면 emotion으로 스타일 컴포넌트를 만들 때 props를 통해 theme에 접근할 수 있게 된다.

const StyleComponent = styled.div`
  background-color: ${props => props.theme.colors.background}
`;

여기까지는 아무 문제가 없었다.

theme 타입에러를 만나다

typescript를 사용할 때는 props에 사용할 타입을 선언하는 과정이 동반되어야한다. 때문에 내가 사용할 타입을 미리 선언해서 사용하기로 했다.

export interface StylePropTypes {
  theme: {
    colors: Record<keyof typeof theme.colors, string>;
  };
  ...
}
  
const StyleComponent = styled.div`
  background-color: ${(props:Pick<StylePropTypes,'theme'>) => props.theme.colors.background}
`;

//또는

const StyleComponent = styled.div<Pick<StylePropTypes,'theme'>>`
  background-color: ${(props) => props.theme.colors.background}
`;

그런데 이런 에러를 만났다.

간략하게 해석해보면 theme이 필요한데 누락되어 있다는 얘기였다. 실제로 StyleComponent를 사용할 때는 theme을 prop으로 줄 필요가 없다. 이미 루트 컴포넌트에서 ThemeProvider로 theme을 주고 있기 때문에, 굳이 StyleComponent를 사용할 때 theme을 prop으로 넘겨주지 않아도 스타일 컴포넌트 선언 시점에 props.theme 형태로 접근이 가능하기 때문이다.

const Home = () => {
	return <StyleComponent> // <StyleComponent theme={theme}> 이렇게 할 필요가 없다.
      ...
    </StyleComponent>

}

하지만 타입스크립트는 이 사실을 알지 못하는지 왜 theme을 사용할거면서 prop으로 넘기지 않고 있냐고 에러를 내고 있는 것이다.

에러 해결하기

찾아보니 emotion에서 theme을 사용하기 위해서는 emotion.d.ts라는 별도의 type 정의 파일을 만들어야 했다. 가이드를 따라 아래와 같이 작성하니 에러가 사라졌다.

// src/styles/emotion.d.ts

import '@emotion/react'
import {theme} from './theme'

type ThemeTpye = typeof theme

declare module '@emotion/react' {
  export interface Theme extends ThemeTpye {}
}

참고 링크 1: https://stackoverflow.com/questions/64537040/emotion-theming-with-typescript-property-x-does-not-exist-on-type-object-t

참고 링크 2: https://velog.io/@yeogenius/React-Emotion.js-%EB%A1%9C-Theme-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0

profile
React-Native 개발블로그
post-custom-banner

0개의 댓글