React에서 데이터는 부모로부터 자식으로 props를 통해 전달된다. 그러나 컴포넌트를 나누다보면 하나의 어플리케이션 안에 여러 컴포넌트에 전달해줘야 하는 경우 props가 자식에서 자식으로 타고 타고 내려가는 props-drilling
현상이 나타나 props가 어디서 어떻게 전달되는지 찾기가 힘들어지고 코드가 지저분해진다.
state management 를 사용하면
부모 -> 자식
간 계층구조로 props를 내려주는것이 아니라 어느 컴포넌트에서나 필요한 props에 직접적으로 접근할 수 있다.
npm install recoil
index.tsx
파일에서 App 컴포넌트를 RecoilRoot
컴포넌트로 감싸준다.atoms.ts
파일을 생성한다.// index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { QueryClient, QueryClientProvider } from "react-query";
import { RouterProvider } from "react-router-dom";
import { RecoilRoot } from "recoil";
import router from "./Router";
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Failed to find the root element");
const root = ReactDOM.createRoot(rootElement);
const queryClient = new QueryClient();
root.render(
<React.StrictMode>
<RecoilRoot> //Recoil 셋팅
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</RecoilRoot>
</React.StrictMode>
);
atom function을 사용하기 위해서는 두가지가 필요하다.
key
값default
import { atom } from "recoil";
export const isDarkAtom = atom({
key: "isDark",
default: false,
});
내가 atom에 담긴 정보가 필요한 컴포넌트 내에서 const 변수명 = useRecoilValue(아톰파일에서지은변수명)
을 작성한다.
// App.tsx
import { createGlobalStyle, ThemeProvider } from "styled-components";
import { ReactQueryDevtools } from "react-query/devtools";
import { Outlet } from "react-router-dom";
import Header from "./routes/Header";
import { darkTheme, lightTheme } from "./thems";
import { useRecoilValue } from "recoil";
import { isDarkAtom } from "./routes/atoms";
function App() {
const isDark = useRecoilValue(isDarkAtom);
return (
<>
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<GlobalStyle />
<ReactQueryDevtools initialIsOpen={true} />
<Header />
<Outlet />
</ThemeProvider>
</>
);
}
export default App;
useSetRecoilState는 매개변수로 atom을 받고, atom을 변경하는 함수를 반환한다.
const 변경함수명 = useSetRecoilState(기본값수정할아톰파일의변수명)
변경함수명(변경할값)
// Header.tsx
import { Link } from "react-router-dom";
import { useRecoilValue, useSetRecoilState } from "recoil";
import { isDarkAtom } from "./atoms";
const Header = () => {
const isDark = useRecoilValue(isDarkAtom);
const setDarkAtom = useSetRecoilState(isDarkAtom);
const toggleDarkAtom = () => setDarkAtom((prev) => !prev);
return (
<HeaderWrap>
<HeaderList>
<li>
<Link to={"/"}>Home</Link>
</li>
<li>
<button onClick={toggleDarkAtom}>
{isDark ? "Light Mode" : "Dark Mode"}
</button>
</li>
</HeaderList>
</HeaderWrap>
);
};
atom이 변경되면 컴포넌트도 변경된 값으로 리렌더링된다.