일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- css
- sup태그
- iframe
- Checked 의사 클래스
- padding 속성
- 임베디드
- id 선택자
- not 의사클래스
- RGBA
- html
- 인접 형제 결합자
- iframe 태그
- 아두이노
- 일반 형제 결합자
- reveal in file explorer
- background-color 속성
- width속성
- sub태그
- height속성
- br 태그
- focus 의사클래스
- html 태그
- i 태그
- RGB
- tag html
- Live Server
- html tag i
- go live
- 전체 선택자
- 자식결합자
- Today
- Total
so woon!
[STYLED COMPONENTS] Recoil을 사용하지 않고 darkTheme, lightTheme 만들기 본문
[STYLED COMPONENTS] Recoil을 사용하지 않고 darkTheme, lightTheme 만들기
xowoony 2023. 4. 14. 14:58학습일 : 2023. 04. 14
Recoil을 사용하지 않고 만드는 버전을 알아보자
Recoil 없이 다크모드/라이트모드 스위치를 구현하기 위해서는
<index.tsx>
기존에 index.tsx에 있는 ThemeProvider를 App.tsx로 옮긴다.
(옮기는 이유는 어플리케이션의 state에 기반하여 바꾸기 위해서임)
이동 전
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
</QueryClientProvider>
);
이동 후
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
<App.tsx>
이동 전
function App() {
return (
<>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</>
);
}
export default App;
이동 후
import { ThemeProvider, createGlobalStyle } from "styled-components";
import { darkTheme, lightTheme } from "./theme"; // import
function App() {
return (
<>
<ThemeProvider theme={darkTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
이로써 theme을 render 하는 ThemeProvider를 index.tsx에서 App component로 가져오게 되었다.
<theme.ts>
darkTheme과 lightTheme을 작성해준다.
import { DefaultTheme } from "styled-components";
export const darkTheme: DefaultTheme = {
bgColor: "rgb(62 62 45)",
textColor: "#f5f6fa",
accentColor: "#e1b12c",
boxColor: "#2b281b"
}
export const lightTheme: DefaultTheme = {
bgColor: "#c5c4b8",
textColor: "black",
accentColor: "#e1b12c",
boxColor: "rgb(173 167 141)"
};
<App.tsx>
darkTheme, lightTheme을 import 해준다. (난 아까 이미 해줬음)
그리고 ThemeProvider에 theme prop으로 삼항연산자를 써줌
import { darkTheme, lightTheme } from "./theme";
function App() {
const [isDark, setIsDark] = useState(false);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
이제 isDark를 true나 false로 toggle하는 function을 만들도록 한다.
<App.tsx>
setState function을 사용할 때 두가지 옵션이 있다. (참고)
1. const toggleDark = () => setIsDark(true); 그냥 이렇게 value를 보내거나
2. const toggleDark = () => setIsDark(); value 대신 function을 보내거나.
이 function은 첫번째 argument로 현재의 state를 가짐.
2. 를 사용 - 현재를 current로 두고 그 반대를 return 하도록 만든다.
isDark가 true이면 false를 return 하고, false이면 true를 return하게 된다.
const toggleDark = () => setIsDark((current) => !current);
button 을 만들어 주고 onClick으로 toggleDark를 준다.
그럼 클릭시 state가 바뀌고 theme이 바뀌게 되어서 다크모드로 전환된다.
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
<button onClick={toggleDark}>테마 변경</button>
</ThemeProvider>
<App.tsx>
전체 코드
function App() {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((current) => !current);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
<button onClick={toggleDark}>테마 변경</button>
</ThemeProvider>
</>
);
}
export default App;
실행결과
클릭시 다크모드, 라이트모드로 바뀌는 것을 확인할 수 있다.
총 정리
1. App.tsx
function 을 Router 로 보냄
import { ThemeProvider, createGlobalStyle } from "styled-components";
import Router from "./Router";
import { ReactQueryDevtools } from "react-query/devtools";
import { darkTheme, lightTheme } from "./theme";
import { useState } from "react";
function App() {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((current) => !current);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router toggleDark={toggleDark} />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
2. Router.tsx
그다음 Router에서 Coins로 보냄
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Coins from "./routes/Coins";
import Coin from "./routes/Coin";
interface IRouterProps {
toggleDark: () => void;
}
function Router({ toggleDark }: IRouterProps) {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Routes>
<Route path={`/`} element={<Coins toggleDark={toggleDark} />} />
<Route path="/:coinId/*" element={<Coin />} />
</Routes>
</BrowserRouter>
);
}
export default Router;
3. Coins.tsx
그러고 나서야 Coins에서 이 function을 가지게 된다.
import { Link } from "react-router-dom";
import styled from "styled-components";
import { useQuery } from "react-query";
import { fetchCoins } from "../api";
import { Helmet } from "react-helmet";
interface ICoinsProps {
toggleDark: () => void;
}
function Coins({toggleDark}:ICoinsProps) {
// useQuery를 통해 Coins 를 fetch
const { isLoading, data } = useQuery<ICoin[]>("allCoins", fetchCoins);
return (
<Container>
<Helmet>
<title>Thorn Coin</title>
</Helmet>
<Header>
<Link to={"/"}>
<Title>Thorn Coin</Title>
</Link>
<SubTitle>Grab Your Own Coin!</SubTitle>
<button onClick={toggleDark}>테마 변경</button>
</Header>
{isLoading ? (
<Loader>로딩중입니다...</Loader>
) : (
<CoinsList>
{data?.slice(0, 100).map((coin) => (
<Coin key={coin.id}>
<Link to={`/${coin.id}`} state={coin}>
<Img
src={` https://cryptocurrencyliveprices.com/img/$ {coin.id}.png`}
alt=""
/>
{coin.name}
</Link>
</Coin>
))}
</CoinsList>
)}
</Container>
);
}
export default Coins;
'Styled Components > 개념정리' 카테고리의 다른 글
[STYLED COMPONENTS] chart 탭에 theme 적용하기 (0) | 2023.04.14 |
---|---|
[STYLED COMPONENTS] Theme 버튼 페이지 header로 옮기기 (0) | 2023.04.14 |
[STYLED COMPONENTS] Themes (0) | 2023.03.29 |
[STYLED COMPONENTS] 컴포넌트 안에서 컴포넌트 타겟팅 하기 (0) | 2023.03.29 |
[STYLED COMPONENTS] styled 안 target 처리하기 (0) | 2023.03.28 |