실전 프로젝트에서는 원래 배운 내용들을 깃허브에 올리는 방식이 아닌 하루하루 진행 상황과 느낀점들을 기록하기 위해서 벨로그에 TIL을 작성하기로 했다.
index.tsx에 app을 로 감싸준다.
import { RecoilRoot } from "recoil";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<BrowserRouter>
<RecoilRoot>
<App />
</RecoilRoot>
</BrowserRouter>
);
reportWebVitals();
고유 이름인 key와 원하는 값인 default를 넣어준다.
이때 default 값을 [] 배열로 넣으면 map을 돌릴 수 있다.
import { atom, selector } from "recoil";
export const data = atom({
key: "data",
default: [
{
id: 1,
subject: "제목1",
category: "음식"
},
{
id: 2,
subject: "제목2",
category: "음식"
},
{
id: 3,
subject: "제목3",
category: "스포츠"
},
{
id: 4,
subject: "제목4",
category: "음식"
},
]
});
데이터 조회만(getter) 하고 싶은 경우 = RecoilValue
setter 만 쓰고 싶은 경우 = useSetRecoilState 를 사용한다.
출력할 때는 useState 쓰는 것처럼 useRecoilState를 사용, getter, setter로 사용한다.
import { useRef } from "react";
import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil";
import { category, select } from "./atoms";
function App() {
// const [list, setList] = useRecoilState(data);
// const resetTest = useResetRecoilState(data);
const [list, setList] = useRecoilState(select);
const [nowCategory, setNowCategory] = useRecoilState(category);
const ref = useRef(null);
const onClick = (e) => {
setList(current => [...current, { id: Date.now(), subject: ref.current.value, category: nowCategory }]); // 불변성
}
const onChange = (e) => {
setNowCategory(e.target.value);
}
return (
<div>
<select onChange={onChange}>
<option value="음식">음식</option>
<option value="스포츠">스포츠</option>
</select>
{list?.map((v, i) => {
return <div key={i}>{v.subject}</div>
})}
<input type="text" ref={ref} />
<button onClick={onClick}>추가</button>
</div>
);
}
export default App;
setList로 default 값을 변경할 때는 불변성을 지켜야한다.
기존의 값을 유지해야하므로 current => ...current로 작성한다.
default 값을 원래대로 돌릴 때는 useRestRecoilState( 변수명 ); 을 사용한다.
Selector는 순수 함수이고 atom이나 다른 selector의 입력값으로 받는다.
이러한 상위 atom이나 selector가 업데이트 되면 selector 함수는 다시 계산될 것이다.
컴포넌트들은 atom처럼 selector를 구독할 수 있으며, selector가 변화하면 리렌더링이 일어난다.
selector는 상태에 기반하여 파생된 데이터를 계산할 때 사용된다.
최소한의 상태가 atom에 저장되어 있고 효율적으로 함수에 의해 계산되기 때문에 취약한 상태를 가지는 것을 피할 수 있다.
selector가 계속하여 어떤 컴포넌트가 필요로 하고 어떠한 상태에 그들이 의존하는지를 추적하기 때문에 이러한 함수적 접근은 매우 효율적이다.
예 ) data의 카테고리에 "음식" 만 뽑아서 보고 싶은 경우 ?
: data를 가져와서 리스트를 뿌려주는게 아니라,
selector를 가져오는 것 !
import { atom, selector } from "recoil";
export const data = atom({
key: "data",
default: [
{
id: 1,
subject: "제목1",
category: "음식"
},
{
id: 2,
subject: "제목2",
category: "음식"
},
{
id: 3,
subject: "제목3",
category: "스포츠"
},
{
id: 4,
subject: "제목4",
category: "음식"
},
]
});
export const category = atom({
key: "category",
default: "음식"
})
// 내 데이터를 원하는 형태로 가공해서 출력, 수정하고 싶을 때 사용
export const select = selector({
key: "data2",
get: ({get}) => {
const oldList = get(data);
const cat = get(category);
return oldList.filter((v) => v.category === cat);
},
set: ({set}, newValue) => {
set(data, newValue)
console.log(newValue);
}
});
selector 함수 안에는 get함수와 set함수가 존재하고
get 함수로 기존 atom에 데이터를 받아오고, set 함수로 바꿔준다.