일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- height속성
- Live Server
- 전체 선택자
- focus 의사클래스
- Checked 의사 클래스
- sup태그
- 임베디드
- i 태그
- br 태그
- RGBA
- 인접 형제 결합자
- html tag i
- 아두이노
- background-color 속성
- RGB
- sub태그
- html 태그
- 일반 형제 결합자
- iframe
- html
- padding 속성
- 자식결합자
- not 의사클래스
- iframe 태그
- reveal in file explorer
- css
- id 선택자
- tag html
- go live
- width속성
- Today
- Total
so woon!
[RECOIL] Recoil 시작하기 + Recoil을 사용하여 다크모드 구현하기 본문
학습일 : 2023. 04. 15
Recoil을 사용하지 않았던 개발환경에서는
단순한 작업일 경우 유용하게 쓸 수 있었지만
작업의 양이 많아질 경우 prop을 쭉 내려 보내서 사용하는 global state가
다소 비효율적이다.
예를 들어 로그인한 사용자의 경우
많은 컴포넌트에서 다른 모습을 보여주어야 한다고 가정했을 때,
이런 방식으로 그 많은 컴포넌트에 prop을 내려주어야 하는
너무 비효율적인 일이 발생할 것이다.
따라서 이러한 이유로 상태관리가 필요한 것인데,
Recoil을 사용함으로 인해
전처럼 isDark를 부모가 자식에게 prop을 내려주는 계층 구조 대신
atom을 형성하고 그 안에 있는 value가 필요한 경우 접근할 수 있게 하는 원리이다.
필요로 하는 component가 직접 atom에 연결되는 것이다.
Recoil을 사용하기 위해
터미널에 입력하여 설치한다.
npm install recoil
Recoil을 사용해보기 위해 전에 적어주었던 theme을 위해
prop을 일일히 전달해주었던 그 모든 과정들을 다 지워주도록 하겠다.
<App.tsx>
수정 전
function App() {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((current) => !current);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router isDark={isDark} toggleDark={toggleDark} />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
수정 후
function App() {
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router/>
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
<Router.tsx>
수정 전
interface IRouterProps {
toggleDark: () => void;
isDark: boolean;
}
function Router({ toggleDark, isDark }: IRouterProps) {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Routes>
<Route path={`/`} element={<Coins toggleDark={toggleDark} />} />
<Route path="/:coinId/*" element={<Coin isDark={isDark} />} />
</Routes>
</BrowserRouter>
);
}
export default Router;
수정 후
interface IRouterProps {
}
function Router({}: IRouterProps) {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Routes>
<Route path={`/`} element={<Coins/>} />
<Route path="/:coinId/*" element={<Coin/>} />
</Routes>
</BrowserRouter>
);
}
export default Router;
<Coin.tsx>
수정 전
interface ICoinProps {
isDark: boolean;
}
function Coin({ isDark }: ICoinProps) {
...
{/* 중첩 라우팅*/}
<Routes>
<Route path="chart" element={<Chart isDark={isDark} coinId={coinId!} />} />
<Route path="price" element={<Price />} />
</Routes>
}
수정 후
interface ICoinProps {
}
function Coin({ }: ICoinProps) {
...
{/* 중첩 라우팅*/}
<Routes>
<Route path="chart" element={<Chart coinId={coinId!} />} />
<Route path="price" element={<Price />} />
</Routes>
}
<Coins.tsx>
수정 전
interface ICoinsProps {
toggleDark: () => void;
}
function Coins({toggleDark}:ICoinsProps) {
...
<button onClick={toggleDark}>테마 변경</button>
}
수정 후
interface ICoinsProps {
}
function Coins({}:ICoinsProps) {
...
}
<Chart.tsx>
수정 전
interface ChartProps {
coinId: string;
isDark: boolean;
}
function Chart({ coinId, isDark }: ChartProps) {
...
options={{
theme: {
mode: isDark ? "dark" : "light",
},
}
수정 후
interface ChartProps {
coinId: string;
}
function Chart({ coinId }: ChartProps) {
...
options={{
theme: {
mode: false ? "dark" : "light",
},
}
다 지워줬기 때문에 이제 index.tsx로 간다.
<index.tsx>
<RecoilRoot>로 감싸준다.
root.render(
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</RecoilRoot>
);
이제 드디어 아톰을 만들러 간다.
src 폴더 밑에 atoms.ts 파일을 생성해줌
<atom.ts>
import { atom } from "recoil";
export const isDarkAtom = atom({
// key : "이름이고 유일해야함"
// default : 기본적으로 둘 값
key: "isDark",
default: false,
});
아톰을 작성해주었기 때문에 이제는 App과 Chart를 atom과 연결해야 한다.
<App.tsx>
useRecoilValue function을 작성한다.
import { useRecoilValue } from "recoil";
import { isDarkAtom } from "./atom";
function App() {
useRecoilValue(isDarkAtom);
return (
<>
<ThemeProvider theme={false ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
그러고선 value를 받아보자.
const isDark를 작성
어플리케이션이 isDarkAtom으로 연결되고, isDarkAtom의 기본값은 false이다.
function App() {
const isDark = useRecoilValue(isDarkAtom);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
export default App;
이제 Chart 탭을 isDarkAtom으로 연결할 차례이다.
useRecoilValue를 작성해준다.
그러고 밑에서 사용해주면 된다.
<Chart.tsx>
import { useRecoilValue } from "recoil";
import { isDarkAtom } from "../atom";
function Chart({ coinId }: ChartProps) {
...
// 테마 적용을 위한 atom
const isDark = useRecoilValue(isDarkAtom);
// 차트 속성 지정해주는 부분임
options={{
theme: {
mode: isDark ? "dark" : "light",
},
}
이제 atom.ts에서
export const isDarkAtom = atom({
key: "isDark",
default: false, // 이 부분이 바뀌면 theme이 전환된다.
});
default가 false이면 라이트모드, true로 바꿔주면 다크모드로 변하게 된다.
이번에는 Atom의 value를 어떻게 수정하는지 알아보자
Atom을 수정할 컴포넌트로 이동한다.
<Coins.tsx>
useRecoilValue를 쓰는 것은 아니고 비슷한 hook인 useSetRecoilState를 쓸 것이다.
useSetRecoilState(아톰이 들어간다);
import { useSetRecoilState } from "recoil";
import { isDarkAtom } from "../atom";
function Coins() {
...
// setter function 은 value를 설정(set) 하는 function이다.
const setDarkAtom = useSetRecoilState(isDarkAtom);
...
// button을 추가해주고 onClick에 setDarkAtom으로 현재에서 반대로 리턴해주면 된다.
<Header>
<Link to={"/"}>
<Title>Thorn Coin</Title>
</Link>
<SubTitle>Grab Your Own Coin!</SubTitle>
<button onClick={() => setDarkAtom((prev) => !prev)}>Toggle Mode</button>
</Header>
-정리-
1. App.tsx에서는 useRecoilValue를 통해 value를 가져오고 있고,
2. Coins.tsx에서는 function을 가져오는데, 이 function이 isDarkAtom 의 value를 수정할 것이다.
이 setDarkAtom function은 React의 setState와 같은 방식으로 작동하게 된다.
Recoil을 사용한 실행결과
한 세배정도 수고가 덜어진 느낌이다.
'Recoil > 개념정리' 카테고리의 다른 글
[RECOIL] Selector - set 사용하기 (0) | 2023.04.25 |
---|---|
[RECOIL] 로컬 스토리지 저장방법 (0) | 2023.04.25 |
[RECOIL] 카테고리별로 todolist 작성하기 + enum으로 카테고리 관리하기 (0) | 2023.04.21 |
[RECOIL] Selector2 (0) | 2023.04.20 |
[RECOIL] Selector1 (0) | 2023.04.20 |