(16) React- Recoil
# Recoil?
=> react.js에서 사용할 수 있는 state management library
한마디로 state대신.
# necessity of state
1. recoil을 사용하지 않았을 때,
app에서 만든 light/dark mode에 대한 toggle을 coins에서 사용하기 위해
app => router => coins 순서로 보내준다.
chart에서도 사용하기 위해서는
app => router => coin => chart 순서로 보내준다.
function App() {
//1. lightmode/darkmode상태 대한 state를 만든다
const [isDark, setIsDark] = useState(false);
//2. 상태를 변경시켜줄수 있는 toggle function을 만들자
//2-1. state를 만들때 특징은 value가 아닌 funcion을 보낸다.
const toggleDark = () => setIsDark((current) => !current);
// setIsDark가 ture이면(current) false를 return하고,
// setIsDark가 false이면(current) true를 return한다.
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router isDark={isDark} toggleDark={toggleDark} />
<ReactQueryDevtools initialIsOpen={true}/>
</ThemeProvider>
</>
);
}
interface IRouterProps{
toggleDark: () => void;
// app파일에서 toggleDark 함수의 return할 반환값이 없다는것을 알려줘야함
// 어떠한 argument도 받지 않고 void를 return하는 함수인것
isDark: boolean;
}
function Router({toggleDark,isDark}:IRouterProps){
return(
<BrowserRouter>
<Routes>
<Route path="/*"
element={<Coins toggleDark={toggleDark}/>}/>
<Route path="/:coinId/*"
element={<Coin isDark={isDark}/>}/>
</Routes>
</BrowserRouter>
);
}
export default Router;
//coin.tsx
interface ICoinProps{
isDark: boolean;
}
function Coin( {isDark}:ICoinProps) {
return(
<Route path="chart"
element={<Chart isDark={isDark}/>}/>
<Route path="price" element={<Price/>}/>
</Routes>
)
interface ChartProps {
// mode변경을 위해 coin으로부터 받은 props
isDark: boolean;
}
function Chart({isDark}:ChartProps){
return(
<div>
options={{
theme:{
mode: isDark ? "dark" : "light",
},
</div>
)
}
interface ICoinsProps{
toggleDark: () => void;
// 여기에서도 app에서 보내는것과 마찬가지
}
function Coins({toggleDark}:ICoinsProps){
return(
<Title>코인</Title>
<button onClick={toggleDark}>Toggle Mode</button>
)
}
2. recoil을 사용할때,
2-1. 사용법
(1) recoil 설치 => npm i recoil
(2) index 파일에 recoilroot태그 넣기 => RecoilRoot로 import 됨.
// index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { QueryClient,QueryClientProvider } from 'react-query';
import { RecoilRoot } from 'recoil';
import { ThemeProvider } from 'styled-components';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
const queryClient = new QueryClient()
root.render(
<React.StrictMode>
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<App/>
</QueryClientProvider>
</RecoilRoot>
</React.StrictMode>
);
(3) atom에 관한 파일 만들기
=> recoil을 통해 atom 을 사용 할 수 있다.
atom이라는 component를 만들고 거기에 value를 정해서 넣어놓은뒤 필요한 component에게 바로 전달해준다.
=> global state를 어플리케이션의 분리된 공간에서 관리하는 것이 훨씬 좋은 방법이다.
atom은 key,default 두가지 속성이 필요하다.
import {atom} from "recoil";
export const isDarkAtom = atom({
key:"isDark",
default:false,
});
(4) app 파일에서 useReCoilValue를 사용해서 recoil,atom을 import
function App() {
const isDark = useRecoilValue(isDarkAtom);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router/>
<ReactQueryDevtools initialIsOpen={true}/>
</ThemeProvider>
</>
);
2-1. atom value 수정
recoil을 사용하지 않았을때 만든것처럼 하기위해,
coins에서 recoil을 수정해서 사용할 것이다.
(1) recoil을 통해 useSetReCoilState를 사용하고 atoms에서 만든 isDarkAtom value를 가져온다.
그리고 그것을 setDarkAtom에 넣어준다.
setDarkAtom 함수는 일반적인 react의 setState 함수와 똑같이 작용한다.
(2) 그리고 toggleDarkAtom을 만들었는데 이 함수는 toggle의 역할을 한다.
(3) 그리고 button을 만들어서 위에서 만든 toggleDarkAtom에 관한 이벤트를 부여한다.
//coins.tsx
function Coins(){
const setDarkAtom = useSetRecoilState(isDarkAtom);
const toggleDarkAtom = () => setDarkAtom((current) => !current);
return(
<Header>
<Title>코인</Title>
<button onClick={toggleDarkAtom}>Toggle Mode</button>
</Header>
)}
# 결론
recoil을 사용함으로써, 계속 state를 넘겨주지 않아도 된다.
component를 만들고 그곳에 value를 정해 놓으면 direct로 가져다 쓸수 있다.