create-react-app 홈페이지에서 타입스크립트 추가 및 생성하는 방법을 찾아 볼 수 있다.
npx create-react-app my-app --template typescript
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
이때 주의해야할 점은, 파일 확장자명도
.ts
(타입스크립트만).tsx
(타입스크립트 + 리액트) 로 같이 수정을 해주어야한다.
그리고 타입스크립트를 기반으로 만들어지지 않은 라이브러리는 에러가 나기때문에 타입스크립트 기반으로 만든 버전을 install 해야한다
npm i --save-dev @types/styled-components
스타일드 컴포넌트 홈페이지에서 나온 방법을 적용해 보자
@types/styled-components
파일을 설치 해줬으므로 두번째 단계로 바로 넘어간다styled.d.ts
을 만든다(확장자명이 d.ts)// import original module declarations
import 'styled-components';
// and extend them!
declare module 'styled-components' {
export interface DefaultTheme {
borderRadius: string;
colors: {
main: string;
secondary: string;
};
}
}
타입스크립트에 대한 선언(선언파일: 타입스크립트를 위한 일종의 설명 파일)이 없는 패키지를 사용할 때
- 터미널에
npm i --save-dev @types/패키지명
을 입력해 보거나- 유명한 라이브러리들을 모아놓은 Definetely Typed 레포지토리에서 다운로드 가능하다.
이 파일에 내가 작업할 테마들의 색상을 지정한다.
import { DefaultTheme } from "styled-components";
export const lightTheme: DefaultTheme = {
bgColor: "whitesmoke",
textColor: "#222",
btnColor: "teal",
};
export const darkTheme: DefaultTheme = {
bgColor: "#222",
textColor: "whitesmoke",
btnColor: "tomato",
};
App 컴포넌트를 ThemeProvider 컴포넌트로 감싸고 theme 오브젝트를 작성해 준다.
import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import App from "./App";
import { darkTheme, lightTheme } from "./thems";
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Failed to find the root element");
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
</React.StrictMode>
);
ThemeProvider로 감싸준 컴포넌트에서는 props로 theme에 접근할 수 있게 된다
import styled from "styled-components";
function App() {
const Container = styled.div`
background-color: ${(props) => props.theme.bgColor};
`;
const H1 = styled.h1`
color: ${(props) => props.theme.textColor};
`;
return (
<Container>
<H1>fully protected</H1>
</Container>
);
}
export default App;
자바스크립트와 동일한 방식으로 작동하지만 theme을 타입화 해줌으로써 완전히 보호할 수 있다.
보통 App 컴포넌트에는 createGlobalStyle
을 사용하여 css 초기세팅을 잡아주는 것만 하고 컴포넌트를 분리하는것이 깔끔하다
import { createGlobalStyle, ThemeProvider } from "styled-components";
import { darkTheme } from "./thems";
const GlobalStyle = createGlobalStyle`
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@300;400&display=swap');
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, menu, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
main, menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
display: block;
}
/* HTML5 hidden-attribute fix for newer browsers */
*[hidden] {
display: none;
}
* {
box-sizing: border-box;
}
body {
font-weight: 300;
line-height: 1.2;
font-family: 'Source Sans Pro', sans-serif;
background-color: ${(props) => props.theme.bgColor};
color: ${(props) => props.theme.textColor};
}
menu, ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a {
text-decoration: none;
color: inherit;
}
`;
function App() {
return (
<>
<GlobalStyle />
</>
);
}
export default App;