react state management를 위한 라이브러리
state management 라이브러리가 필요한 이유 - 하위 컴포넌트가 state를 받기위해 여러 하위 컴포넌트를 거쳐가야하는 번거로움을 줄이기 위해
Atom
recoil에서 redux store 역활을 하는 값을 저장하고 있는 장소
Atom값을 관찰하면 수정되는경우 리렌더링 된다.
설치
npm install recoil
최상위 컴포넌트(index.tsx)에서 RecoilRoot로 감싸준다.
// index.tsx
import App from "./App";
import React from "react";
import ReactDOM from "react-dom/client";
import { RecoilRoot } from "recoil";
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
<RecoilRoot>
<App />
</RecoilRoot>
);
Atom을 만들어 준다.
// atoms.ts
// atom을 만들때 필요한 건 고유한키, 디폴트값 이다.
import { atom } from "recoil";
export const isDarkAtom = atom({
key: "isDark",
default: false
});
useRecoilValue
state값을 가져올 수 있다.
import { isDarkAtom } from "./atoms";
import { useRecoilValue } from "recoil";
function App() {
const isDark = useRecoilValue(isDarkAtom);
....
}
export default App;
useSetRecoilState()
import { useSetRecoilState } from "recoil";
import { isDarkAtom } from "../atoms";
const Coins = () => {
const setDarkAtom = useSetRecoilState(isDarkAtom);
const toggleDarkAtom = () => setDarkAtom((current) => !current);
return (
<Title>
Coins
<button onClick={toggleDarkAtom}>toggle theme</button>
</Title>
};
}
useRecoilState
value와 modifier 함수를 반환한다. setState와 정말 비슷한 형태
// useRecoilState를 사용하지 않을 때
const todos = useRecoilValue(toDoState);
const setTodos = useSetRecoilState(toDoState);
// useRecoilState를 사용할 때
const [todos, setTodos] = useRecoilState(toDoState);
useRecoilState사용하는 방법 2가지
1. value값을 넘겨서 state를 변경
2. state를 받아서 함수안에서 변형 후 리턴 할 수 있다.
// allTodos로 현재 state값을 가져온다.
setTodos((allTodos) => {
return {
...allTodos,
[source.droppableId]: copyTodo,
};
});
Immutability 불변성
recoil에서 몇번째 배열요소를 변경하고 싶은경우 바로 값을 변경해주면 안된다.
새로운 배열을 return해야한다.
// orange값을 변경하고 싶은경우
const test = ['apple', 'orange', 'pineapple', 'strawberry'];
const targetIndex = test.indexOf('orange'); // 1
const frontTest = test.slice(0, targetIndex);// ['apple'];
const backTest = test.slice(targetIndex+1) // ['pineapple', 'strawberry'];
const newTest = [...frontTest, 'newfruit', ...backTest] // ['apple', 'newfruit', 'pineapple', 'strawberry']
selectors
atom state값을 가져와서 output을 변형을 준다.
가져오는 atom state값은 변경안된다.
key, get함수(atom값을 가져올 수 있다.), set함수(state값을 변경)를 가진다.
atom 값이 변경되면 selector값도 변한다.
import { atom, selector } from 'recoil';
export interface ITodos {
text: string;
id: number;
category: "TO_DO" | "DOING" | "DONE";
}
export const toDoState = atom<ITodos[]>({
key: "toDos",
default: [],
});
export const toDoSelector = selector({
key: 'todoSelector',
get: ({get}) => {
const toDos = get(toDoState); //atom을 가져온다.
return [
toDos.filter((todo) => todo.category === 'TO_DO'),
toDos.filter((todo) => todo.category === 'DOING'),
toDos.filter((todo) => todo.category === 'DONE'),
]
}
})
위 코드에서 selector로 리턴하는 값이 이중배열이므로
구조분해할당을 사용하여 쉽게 사용할 수 있다
import CreateTodo from "./CreateTodo";
import Todo from "./Todo";
import { toDoSelector } from "../atoms";
import { useRecoilValue } from "recoil";
const TodoList = () => {
const [todos, doing, done] = useRecoilValue(toDoSelector);
return (
<>
<CreateTodo />
<h1>To-Do</h1>
<ul>
{todos.map((todo) => (
<Todo key={todo.id} {...todo} />
))}
</ul>
<h1>Doing</h1>
<ul>
{doing.map((todo) => (
<Todo key={todo.id} {...todo} />
))}
</ul>
<h1>Done</h1>
<ul>
{done.map((todo) => (
<Todo key={todo.id} {...todo} />
))}
</ul>
</>
);
};
export default TodoList;
selector set()
selector도 useRecoilState를 사용할 수 있다.
useRecoilState에 modifier를 사용하면 selector에 있는 set 함수가 실행된다.
selector에 set함수를 이용해서 state값을 변경할 수 있다.
import { atom, selector } from 'recoil';
export const minuteState = atom({
key: 'minute',
default: 0
});
export const hourSelector = selector({
key: 'hourSelector',
get: ({ get }) => {
return get(minuteState) / 60;
},
set: ({ set }, newValue) => {
const minutes = Number(newValue) * 60;
set(minuteState, minutes); //minuteState값을 새로운 value로 set
}
})
'TECH' 카테고리의 다른 글
Framer Motion 애니메이션 라이브러리 (0) | 2023.03.06 |
---|---|
react-router-dom v6 (0) | 2023.03.02 |
React Hook Form (0) | 2023.03.01 |
styled-components 전역 스타일링 (Global style) (0) | 2023.02.24 |
styled-components로 theme적용하기 with Typescript (0) | 2023.02.22 |