React Js Master #6 state management Recoil
Recoil: React JS에서 사용 할 수 있는 state management library
recoil 없이 theme 만들기
1.우선 index .tsx에 있는 themeprovider --> app.tsx로 이동, import
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<App /> </ThemeProvider>
</QueryClientProvider>
app.tsx
import { theme } from "./theme";
import { ThemeProvider } from "styled-components";
function App() {
return (
<>
<ThemeProvider theme={theme}>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
why should we move the to App.tsx to use "state"? Can't we use it on index.tsx?
2. theme.tsx에서 lightTheme, darkTheme 생성 후 app.tsx에서 import 후 theme= 변경
app으로 옮긴 이유 state 사용하기 위해
function App() {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((current) => !current); setIsDark 기본 값:현재
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<button onClick={toggleDark}>ToggleMode</button>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
}
3.button 을 Coins에 title옆에 위치시키기
app.tsx에 있는 toggleDark function을 Coins.tsx에서 접근 할 수 있게 해야함
구조상 app.tsx에 <Router>에 <Coins>존재하니
Router로 app.tsx에있는 prop보내기
app.tsx
function App() {
const [isDark, setIsDark] = useState(false);
const toggleDark = () => setIsDark((current) => !current);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<Router toggleDark={toggleDark} /> //but, Router에서 받을 준비가 안됨 interface설정
<ReactQueryDevtools initialIsOpen={true} />
</ThemeProvider>
</>
);
하Router로 함수 보낼 때 함수 형태를 명시해주어야함
}
Coins에 있는 button에 사용하기위해 두단계나 내려보냄
2.chart도 dark/light 모드에 따라 변경하고 싶음
isDark가 true인지 false인지 알 수 있어야
app.tsx에서 router로 chart로 도 두 단계 보내야함
지금까지 해온 방식
global state는 어플리케이션이 특전 state에 value에 접근해야 사용가능.
const [isLoggedIn , setIsLoggedIn] =useState(false); 유저의 로그인한 걸 모든 Router에 공유해야하는데
대량의 screen, component에 계속 내려보내 작성하여 공유(?) 말도 안됨--> state management가 필요한 이유
단순 react js로 state management를 할때 생기는 불편함:
App에서 컴포넌트로 내려가는 계층구조로 인해서 state와 state manipulation을 일일이 각 component들에 전달해줘야함. (App-Router-Coins // App-Router-Coin-Chart)
Recoil은 state를 따로 bubble에 담아서 각 컴포넌트들이 필요할때 buble에 접속해서 사용할 수 있게 함. (App -> (isDark)
recoil로 사용하기
어플리케이션의 분리된 공간에서 생성하여 연결
1. npm i recoil
2. index.tsx에서 <RecoilRoot>로 감싸기
ReactDOM.render(
<React.StrictMode>
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</RecoilRoot>
</React.StrictMode>,
document.getElementById("root")
);
3. src > atom.ts파일 생성
어떤 컴포넌트던간에 독립적임 .
import { atom } from "recoil";
export const isDarkAtom = atom({
key: "isDark",
default: false,
});
4.useRecoilValue
app.tsx
function App() {
const isDark = useRecoilValue(isDarkAtom);
return (
<>
<ThemeProvider theme={isDark? darkTheme : lightTheme}>
<GlobalStyle />
5. set하기 useSetRecoilState
function Coins() {
const setDarkAtom = useSetRecoilState(isDarkAtom); /기존값 반환
const toggleDarkAtom = () => setDarkAtom((prev) => !prev); //useState처럼 기존 값 사용가능!
const { isLoading, data } = useQuery<ICoin[]>("allCoins", fetchCoins);
return (
<Container>
<Helmet>
<title>코인</title>
</Helmet>
<Header>
<Title>코인</Title>
<button onClick={toggleDarkAtom}>ToggleMode</button>
</Header>
useRecoilValue(state)
Recoil state값을 반환합니다.
이 hook은 암묵적으로 주어진 상태에 컴포넌트를 구독합니다.
이 hook는 읽기 전용 상태와 쓰기 가능 상태에서 모두 동작하므로 컴포넌트가 상태를 읽을 수만 있게 하고 싶을 때에 추천하는 hook입니다. 이 hook을 React 컴포넌트에서 사용하면 상태가 업데이트 될 때 리렌더링을 하도록 컴포넌트를 구독합니다.
ex) const names = useRecoilValue(namesState);
https://recoiljs.org/ko/docs/api-reference/core/useRecoilValue/
useSetRecoilState(state)
Recoil state의 값을 업데이트하기 위한 setter 함수를 반환합니다.
상태를 변경하기 위해 비동기로 사용될 수 있는 setter 함수를 리턴합니다.
setter는 새로운 값이나 이전 값을 인수로 받는 updater 함수를 넘겨줍니다.
ex) const setNamesState = useSetRecoilState(namesState);
https://recoiljs.org/ko/docs/api-reference/core/useSetRecoilState/