코딩/Today I Learn

React Js Master #6 state management Recoil

코딩쪼렙 2022. 5. 9. 18:57
728x90

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>
        </>
    );
}

Question:
why should we move the to App.tsx to use "state"? Can't we use it on index.tsx?
 Yes we can, but I want to send the dark mode prop also to other screens.

 

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로 함수 보낼 때 함수 형태를 명시해주어야함 
}

Router.tsx
Coins.tsx

Coins에 있는 button에 사용하기위해 두단계나 내려보냄 

 

2.chart도 dark/light 모드에 따라 변경하고 싶음

isDark가 true인지 false인지 알 수 있어야 

app.tsx에서 router로 chart로  도 두 단계 보내야함 

 

지금까지 해온 방식 

global state

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/