티스토리 뷰
Recoil 사용법
React의 아버지, 페이스북에서 만든 React 전용 상태관리 라이브러리입니다.
설치, RecoilRoot, 폴더구조, atom, atomHook, selector, selectorFamily 순으로 알아보도록 하겠습니다.
Recoil 설치
npm
npm install recoil
yarn
yarn add recoil
RecoilRoot
Recoil 초기연동할 때 사용됩니다.
Recoil은 Redux에 비해서 초기설정이 쉽습니다.
우선 Redux를 사용할 때 루트에 Provider 태그를 감싸주는 것처럼 Recoil은 RecoilRoot를 감싸줍니다.
// App.js
import { RecoilRoot } from "recoil";
import Home from "./Components/Home";
function App() {
return (
<RecoilRoot>
<Home />
</RecoilRoot>
);
}
export default App;
끝입니다. 이제 사용해 보겠습니다.
폴더구조
폴더구조는 상황이나 사람에 따라 차이가 있습니다.
저는 이렇게 src안에 폴더구조를 짰습니다.
atom
Recoil에서 상태(state)를 정의하는 개념입니다.
컴포넌트에서 구독과 업데이트가 가능하며 atom의 값이 변경될 시 구독하고 있는 컴포넌트가 리렌더링 됩니다.
우선 더미데이터로 작성한 todoList의 데이터를 받아와서 저장해 놓을 atom(state)을 정의하겠습니다.
// recoil/atoms/todoState.js
import { atom } from "recoil";
export const todoState = atom({
key: "todoState",
default: []
})
정의한 atom(state)을 컴포넌트에서 useRecoilState() Hook을 사용하여 구독하고 todoList의 데이터를 담아보겠습니다.
// components/TodoForm.jsx
import axios from "axios";
import { useEffect, useState } from "react";
import { useRecoilState } from "recoil";
import { todoState } from "../recoil/atoms/todoState";
function TodoForm() {
const [todos, setTodos] = useRecoilState(todoState); //useState와 거의 비슷한 사용법
useEffect(() => {
axios
.get("/data/data.json")
.then((res) => {
setTodos(res.data.data);
})
.catch((err) => {
console.log(err);
});
}, []);
console.log(todos)
return (
<>
{todos.map((v) => {
return (
<div style={{ marginBottom: ".5rem" }} key={v.id}>
<span>{v.text}</span>
<span style={{ marginLeft: "2rem", fontSize: ".8rem" }}>{v.state === true ? "완료" : "미완료"}</span>
</div>
);
})}
</>
);
}
export default TodoForm;
매력적 이게도 useState()와 거의 같은 사용법입니다.
정보를 잘 받아온 것을 볼 수 있습니다.
atom Hook
위처럼 atom(state)으로 정의된 상태를 컴포넌트에서 Hook을 이용하여 사용합니다.
위 코드에선 useRecoilState를 사용하여 useState처럼 첫 번째 파라미터에선 상태를 받아오고 두 번째 파라미터에선 setter함수를 받아왔습니다.
아래는 Hook들을 정리해 놓았습니다.
- useRecoilState: 1번째 파라미터는 atom의 상태, 2번째 파라미터는 setter 함수를 가져옵니다. (읽기, 쓰기)
- useRecoilValue: atom의 상태만 가져옵니다. (읽기)
- useSetRecoilState: setter 함수만 가져옵니다. (쓰기)
- useResetRecoilState: atom의 상태를 본래 default값으로 초기화합니다.
selector
selector는 atom(state)를 기반으로 파생된 데이터를 만들어내는 데 사용됩니다.
위 예제 코드에서 todoList 데이터를 받아와서 atom(state)에 저장하였습니다.
그렇게 받아온 데이터에서 selectors를 이용하여 기존 atom(state)는 유지하며 todoList에서 완료된 작업들만 추려내 보겠습니다.
// recoil/selector/todoSortState.js
import { selector } from "recoil";
import { todoState } from "../atoms/todoState";
export const todoSortState = selector({
key: "todoSortState",
get: ({ get }) => {
const data = get(todoState);
const result = data.filter((v) => v.state === true)
return result
}
})
filter를 사용하여 분류하는 코드를 작성하였습니다.
이제 잘 작동하는지 보겠습니다.
// components/TodoForm.jsx
import axios from "axios";
import { useEffect, useState } from "react";
import { useRecoilState } from "recoil";
import { todoState } from "../recoil/atoms/todoState";
import { todoSortState } from "../recoil/selectors/todoSortState";
function TodoForm() {
const [todos, setTodos] = useRecoilState(todoState); // useRecoilState: 읽기와 쓰기
const sortList = useRecoilValue(todoSortState(work)); // useRecoilValue: 읽기
useEffect(() => {
axios
.get("/data/data.json")
.then((res) => {
setTodos(res.data.data);
})
.catch((err) => {
console.log(err);
});
}, []);
console.log(todos)
console.log(sortList)
return (
<>
{todos.map((v) => {
return (
<div style={{ marginBottom: ".5rem" }} key={v.id}>
<span>{v.text}</span>
<span style={{ marginLeft: "2rem", fontSize: ".8rem" }}>{v.state === true ? "완료" : "미완료"}</span>
</div>
);
})}
</>
);
}
export default TodoForm;
기존 atom(state)는 유지하며 파생된 데이터(완료된 작업)를 잘 가져오는 것을 볼 수 있습니다.
여기까지만 해도 Recoil은 쉽고 간단하고 매력적이라는 것을 알 수 있습니다.
더 나아가 selector에 매개변수를 전달하여 사용하는 법을 알아보겠습니다.
selectorFamily
selector에 매개변수가 필요할 때 사용됩니다.
selector에 매개변수를 전달하여 아래 버튼 3개의 조건에 맞게 동작이 되게 해 보겠습니다.
우선 selector에 매개변수를 넣어줍니다.
const [work, setWork] = useState(true);
const sortList = useRecoilValue(todoSortState(work)); //완료된 작업, 미완료된 작업 상태를 나타내는 work를 파라미터로 담는다.
selectorFamily로 매개변수를 받아와서 사용합니다.
// recoil/selector/todoSortState.js
import { selectorFamily } from "recoil";
import { todoState } from "../atoms/todoState";
export const todoSortState = selectorFamily({
key: "todoSortState",
get: (work) => ({ get }) => {
const data = get(todoState);
const result = work ? data.filter((v) => v.state === true) : data.filter((v) => v.state === false)
return result
}
})
이후 조건부 렌더링을 통해 화면이 바뀌도록 하였습니다.
잘 동작하는 것을 볼 수 있습니다.
마치며
새로고침이 되었을 때 state(상태) 값이 사라지거나 변경되지 않아야 하는 경우가 있습니다.
이를 위해선 state(상태)를 localStorage / sessionStorage에 저장하여 사용해야 합니다.
주로 Redux에선 Redux-persist를 사용하여 localStorage / sessionStorage에 저장합니다.
Recoil에서도 Recoil-persist를 사용하여 Redux보다 더 쉽고 간단하게 localStorage / sessionStorage에 저장합니다.
[React] Recoil-persist 사용하여 localStorage와 sessionStorage에 저장하기
Recoil-persist 사용이유 새로고침 시에도 데이터가 날아가지 않게 관리를 해주어야 할 때가 옵니다. 주로 사용자가 로그인한 상태에서 새로고침을하면 사용자의 로그인 정보 데이터가 날아가게 되
jeonghodong.tistory.com
Recoil
A state management library for React.
recoiljs.org
'React' 카테고리의 다른 글
MUI-Input을 커스텀하여 Input Component 작업하기 (0) | 2024.07.16 |
---|---|
[React] Recoil-persist 사용하여 localStorage와 sessionStorage에 저장하기 (0) | 2023.04.09 |