페이스북이 개발한 전역상태관리 라이브러리
🧔🏻♂️면접관: Recoil로 상태관리를 했는데, 어떤 방식으로 했죠??
👧🏻나: 제가 관리 안했는데여?...
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
⭐React를 만든 곳에서 React 상태관리를 편리하게 도와주려고 개발한 상태관리 라이브러리가 있다?!⭐ 외않씀??
트리의 최상단(선언하는 곳)부터 트리의 말단(사용하는 곳) 까지의 코드 분할이 어려워짐
상태변화는 트리의 뿌리(atoms)로 부터 순수 함수(selectors)를 거쳐 컴포넌트로 흐름
npm i recoil
of
yarn add recoil
const fontSizeState = atom({
key: 'fontSizeState',
default: 14,
});
atom함수 만들기
import { atom } from "recoil";
const fontSizeState = atom({
key: "fontSizeState",
default: 14,
});
export default fontSizeState;
font크기가 증가하는 버튼 만들기
import React from "react";
import { useRecoilState } from "recoil";
import fontSizeState from "../store/fontSizeState";
const FontButton = () => {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return (
<button
onClick={() => setFontSize((size) => size + 1)}
style={{ fontSize }}
>
커지는 버튼
</button>
);
};
export default FontButton;
font크기가 증가하는 text 만들기
import React from "react";
import { useRecoilState } from "recoil";
import fontSizeState from "../store/fontSizeState";
const Text = () => {
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
return <p style={{ fontSize }}> 커진닷 </p>;
};
export default Text;
의문점.. '어? 각각의 컴포넌트인데 state뭔가 연결고리가 없어보이는데, 컴포넌트가 분리된 상태에서도 font사이즈에 대한 state 공유가 가능하다고?'
그래서 직접 코드를 작성해서 실행시킴
import { selector } from "recoil";
import fontSizeState from "./fontSizeState";
const fontSizeLabelState = selector({
key: "fontSizeLabelState",
get: ({ get }) => {
const fontSize = get(fontSizeState);
const unit = "px";
return `${fontSize}${unit}`;
},
});
export default fontSizeLabelState;
❓❓❓❓❓왜? 어째서? 이 부분이 의문이었던 이유
const [state, setState] = useState();
일반적으로 이렇게 쓰니까 당연히 '왜 setState를 다른 곳에서 또 쓴다고???? 으엥???? 그럼 다른 곳에서 쓰는 setState로 상태를 업데이트를 하면 헷갈리지 않을까? 그러면 setState 둘 중 뭐를 써야하지?' 이런 쓸모없는 고민을 했음. 그리고 나는 recoil을 쓰지 않겠다고 다짐함. 하지만 나는 바보였음.
🔔어디에서 setState로 상태를 업데이트를 setState값은 바로 현재 state가 되기 때문에 상관이 없었음
그러니깐,
setValue는 바로 최신의 state로 업데이트 되기 때문 여러곳에서 setValue 함수를 만들어놔도 그 상태 자체가 바로 업데이트 되기 때문에 다른 곳에 만들어진 useSetRecoilState는 서로에게 영향을 미치지 않음
const [fontSize, setFontSize] = useRecoilState(fontSizeState);
이렇게 만들어진 것도, 다른 컴포넌트에서
const setFontSize = useSetRecoilState(fontSizeState)
이렇게 사용될 수 있음
const currentUserIDState = atom({
key: 'CurrentUserID',
default: 1,
});
const currentUserNameQuery = selector({
key: 'CurrentUserName',
get: async ({get}) => {
const response = await myDBQuery({
userID: get(currentUserIDState),
});
return response.name;
},
});
function CurrentUserInfo() {
const userName = useRecoilValue(currentUserNameQuery);
return <div>{userName}</div>;
}
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { RecoilRoot } from "recoil";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<RecoilRoot>
<App />
</RecoilRoot>
);
import { atom } from "recoil";
const todoIdState = atom({
key: "todoIdState",
default: 1,
});
export default todoIdState;
import { selector } from "recoil";
import todoIdState from "./todoIdState";
import axios from "axios";
const todoItemQuery = selector({
key: "todoItemQuery",
get: async ({ get }) => {
const id = get(todoIdState);
const response = await axios.get(
`https://jsonplaceholder.typicode.com/todos/${id}`
);
return response.data;
},
});
export default todoItemQuery;
import React from "react";
import { useRecoilValue } from "recoil";
import todoItemQuery from "./store/todoItemQuery";
function App() {
const data = useRecoilValue(todoItemQuery);
console.log(data);
return <div>{data.title}</div>;
}
export default App;
🖥 atom에 최신상태를 만들어주거나 selector로 값을 받아와서 반환값을 만들어주는 기능도 가능하고, 원하는 상태만을 가져다 쓰거나 업데이트만 시켜주는 것도 가능함 ! 익숙해지면 편리할 것들
느낀점. 리덕스와 리코일을 둘 다 공부했을때, 뭐가 더 낫다 좋다 이것보다 이 부분은 리코일이 편하고 이 부분은 리덕스가 유리하겠다 ! 라는 느낌이 있었음.
자그마한 리코일 실습을 해보면 더 이해가 될 거 같아서 다음엔 쪼그만 실습을 해볼 예정!