보통 리액트에서는 상태관리를 하기 위해 redux, recoil를 많이 사용한다.
니꼬 선생님께서는 recoil를 사용해서 상태관리를 진행할 예정이라 나 또한 recoil를 진행해볼 예정이다.
리액트에서 상태관리는 컴포넌트 간의 데이터 흐름과 데이터의 일관성을 유지하는 것을 의미하는데, recoil를 사용하기 전, 원초적인 상태관리를 해본 후, recoil를 사용해야 하는 점들을 알아보도록 하겠다.
우선 DarkMode와 LightMode를 만들어보자
먼저 index.js에 있던 <ThemeProvider/> 를 가져와 App.tsx에 옮겨주었다.
--> useState를 사용하기 위해서이다!

App 컴포넌트에서 버튼을 생성한 후, theme을 적용시켰다.
먼저 const [isDark, setIsDark] = useState(false); 속성을 이용해
isDark가 true --> darkTheme, false--> lightTheme임을 toggleDark함수에 정의한 후, button의 onClick 속성에 적용시켰다.

저 위에 Toggle Mode 버튼을 누르면 내가 theme에 정의한 색상으로 darkMode, lightMode로 변경되는 것을 확인할 수 있다!
이번에는 chart 부분에 chart를 dark 모드, light 모드 변경을 할 수 있도록 코드를 수정해 보겠다.
자, 먼저 App -> Router -> coin -> chart 순으로 chart 접근이 가능하다.

App에서 Router에 isDark={isDark}를 props로 보낸 뒤,
Router에서 받은 뒤, Coin 컴포넌트에 props로 보내주어야 한다.이후, coin에서 받은 뒤, chart에 props로 보낸뒤,
theme 속성의 mode에 isDark ? 'dark' , 'light' 을 적용시켜주었다. 
그럼 이렇게 light 모드일 경우에는 chart 역시 light 모드로 변경이 되었다!
하지만, 만약 price에 적용하고 싶을 경우에는,
마찬가지로 App -> Router -> Coin -> Price
순으로 전달하고 받고 전달하고 받고를 반복 한 뒤, Price 에 도달할 수 있게 된다.
하지만 정작, App, Price만 isDark 를 사용하지 Router, Coin은 단지 전달하는 역할만 하는 것이다.
이렇게 되면, 사실 어디서부터 시작인지도 살펴야 하고, 거쳐오는 과정에서 오류가 발생할 가능성이 있다. 너무 번거롭기도 하고, 어떠한 속성을 부모에서 자식으로 모두 전달을 거쳐야 한다는 것부터 너무 번거로운 일이다!

Recoil를 시작하기 전에, 니꼬 선생님이 설명해주셨던 화면을 들고 왔다.
React의 상태관리는
isDark 란 속성이 App과 Chart 둘만 쓰이는데도, Chart까지 전달하기 위해 Router, Coin 를 거쳐서 전달이 이루어지는 것이다.
하지만, Recoil를 사용하면 다르다!
Recoil의 가장 큰 특징인
Atom : Recoil의 가장 기본적인 상태 단위이다. 애플리케이션의 모든 컴포넌트에서 접근 가능하며, Atom이 변경될 때마다 해당 Atom을 구독하고 있는 컴포넌트가 자동으로 리렌더링된다.
즉, Atom에 속성을 정의하고, 필요한 곳에서 가져다 쓰면 된다는 것이다!
먼저, npm install recoil를 통해 recoil를 설치하면 된다.

이후, index.js에서 <App/> 컴포넌트를 <RecoilRoot/>를 통해 감싸주면 된다.
그럼 이제, Atom을 생성해보러 가자!
<atom의 기본 형태>
atom({key: 'unique key' ,default: 'default state' })로 생성
atom.ts

key는 유니크한 값으로 isDark로, default값(기본값)은 true로 지정한 atom을 isDarkAtom으로 담아두었다!
이제 Atom을 사용하러 가보자
--> isDarkAtom이 필요한 곳은 App, Chart 컴포넌트 두곳이다.

useRecoilValue를 사용하여 isDarkAtom의 값을 가져와 isDark 변수에 할당하고, 이를 통해 테마를 설정한다.
useRecoilValue는 Atom의 현재 값을 읽기만 하기 때문에, isDark는 true 또는 false 값을 갖게 된다.

chart 컴포넌트도 마찬가지로, useRecoilValue로 isDarkAtom을 불러온 뒤, isDark 변수에 할당했다.
isDarkAtom은 기본값 true로 설정되어 있기 때문에, 현재 dark 모드가 적용될 것이다.
이렇게 사용해보니, props로 부모부터 자식까지 전달하던 react의 상태관리와 달리,
필요한 곳에서 atom을 불러다 사용해 필요한 과정을 생략하고, 필요한 곳에서 바로 사용이 가능하다는 장점을 찾아볼 수 있다.
그럼 이번에는 theme 버튼을 만들어보자
theme 버튼을 눌러서 dark -> light -> dark 테마를 요렇게 변하는 것이다!

useSetRecoilState 를 사용하면 특정 Atom의 상태를 변경할 수 있는 함수를 반환한다.
이 함수는 기존 상태를 기반으로 새로운 상태를 설정하거나, 새로운 상태를 직접 설정할 수 있다
--> React의 setState와 같다고 생각하면 된다.
const setDarkAtom = useSetRecoilState(isDarkAtom); :
const toggleDarkAtom = () => setDarkAtom((prev) => !prev); :
toggleDarkAtom은 setDarkAtom을 사용하여 isDarkAtom의 상태를 토글(반전)하는 함수이다. <button onClick={toggleDarkAtom}>Theme</button>
이건 내가 혼자서 생각해서 한번 해본 것인데,
단순히 버튼으로 theme을 변경하는 것보단. toggle 이미지를 사용해서 버튼을 꾸며보면 어떨까 하는 생각이 들었다!
먼저 fontAwesome에서 원하는 이미지를 찾은 뒤,
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faToggleOn, faToggleOff } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } 을 통해서 사용할 준비를 마친 뒤,
const CustomFontAwesomeIcon = styled(FontAwesomeIcon)`
font-size: 30px;
`;
const setDarkAtom = useSetRecoilState(isDarkAtom);
const [isToggled, setIsToggled] = useState(true);
const toggleDarkAtom = () => {
setIsToggled((prev) => !prev);
setDarkAtom((prev) => !prev);
};
<CustomFontAwesomeIcon
onClick={toggleDarkAtom}
icon={isToggled ? faToggleOff : faToggleOn}
/>
를 적용했다.
styled-component 를 사용해서 <CustomFontAwesomeIcon> 태그를 만든 뒤, onClick 이벤트를 적용했다.
icon 모양 또한, isToggled 를 통해서, isToggled가 true면 faToggleOff 아이콘을, false면 faToggleOn을 사용하도록 코드를 작성해 보았다.
이렇게 적용시키면,
기본화면 - dark Theme

toggle 버튼을 누른 뒤 - light Theme

으로 변경되는 것을 확인할 수 있다!

React, TypeScript, React-Query , Styled-component, recoil 등등
react를 제외하고 처음 접해본 기능들로 열심히 만들어 본 첫번째 니꼬 선생님과 함께하는 프로젝트를 종료했다!
나름 잘 된거 같기도 하고, 아쉽기도 하고, 이제 보니 수정하고 싶은 부분들도 많이 보이는 것 같다.
조금 더 괜찮게 꾸며보면 좋을 것 같다! 💪🏻