Recoil์ Selector๋ Recoil์์ ์ ๊ณตํ๊ณ ์๋ ์์ํจ์์ ๊ฐ๋
์ด๋ค. Selector๋ Derived State
์ฆ, ํ์๋ State๋ฅผ ์ ์ฅํ๋ฉฐ ๊ฐ๊ณตํ์ฌ returnํด ์ค ์ ์๋ ํจ์์ด๋ค. Selector๋ฅผ ์ด์ฉํ์ฌ atom์ ์ ๊ฒ ๋ง๋ค๊ณ ๊ทธ ๊ฐ์ ์ ๊ทผํ๊ธฐ ์ฉ์ดํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค! ๐
โค๏ธโ๐ฅ ์ต์ํ์ ์ํ ์งํฉ๋ง atom์ ์ ์ฅํ๊ณ ๋ค๋ฅธ ๋ชจ๋ ํ์๋๋ ๋ฐ์ดํฐ๋ Selector์ ๋ช ์ํ ํจ์๋ฅผ ํตํด ํจ์จ์ ์ผ๋ก ๊ณ์ฐํจ์ผ๋ก์จ ์ธ๋ชจ์๋ ์ํ์ ๋ณด์กด์ ๋ฐฉ์งํ๋ค.
import { selector } from "recoil";
atom.ts
export const minuteState = atom({
key: "minutes",
default: 0,
});
export const hourSelector = selector({
key: "hours",
get: ({ get }) => {
const minutes = get(minuteState);
return minutes / 60;
},
});
๐๐ป Selector๋ get
ํจ์๋ฅผ ์ด์ฉํด ๋ค์ํ atom์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
App.tsx
const [minutes, setMinutes] = useRecoilState(minuteState);
const hours = useRecoilValue(hourSelector);
const onMinutesChange = (event: React.FormEvent<HTMLInputElement>) => {
setMinutes(+event.currentTarget.value);
};
return (
<div>
<input
value={minutes}
onChange={onMinutesChange}
type="number"
placeholder="Minutes"
/>
<input value={hours} type="number" placeholder="Hours" />
</div>
);
๐๐ป Selector๊ฐ ๋ฐํํ๋ ๊ฐ์ ๋ค๋ฃจ๊ณ ์ถ๋ค๋ฉด useRecoilValue์ ์ธ์์ Selector ์ด๋ฆ์ ๋ฃ์ด ์ฌ์ฉํ๋ค.
โ
๊ฐ์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด useRecoilValue
, set ํจ์๋ ํจ๊ป ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด useRecoilState
๋ฅผ ์ด์ฉํ๋ค.
atom.ts
export const hourSelector = selector<number>({
key: "hours",
get: ({ get }) => {
const minutes = get(minuteState);
return minutes / 60;
},
set: ({ set }, newValue) => {
const minutes = Number(newValue) * 60;
set(minuteState, minutes);
},
});
๐๐ป set ํจ์๋ ๋ ๋ฒ์งธ ์ธ์๋ก ๋ณ๊ฒฝ๋ ๊ฐ์ ๊ฐ์ง ์ ์๋ค. ์ฐ๋ฆฌ๊ฐ ์ ๋ ฅํ ๊ฐ์ ํจ์ ๋ด์์ ๋ณ๊ฒฝํ์ฌ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ง๋ค์ด ์ค ์ ์๋ค.
App.tsx
const [minutes, setMinutes] = useRecoilState(minuteState);
const [hours, setHours] = useRecoilState(hourSelector);
const onMinutesChange = (event: React.FormEvent<HTMLInputElement>) => {
setMinutes(+event.currentTarget.value);
};
const onHoursChange = (event: React.FormEvent<HTMLInputElement>) => {
setHours(+event.currentTarget.value);
};
return (
<div>
<input
type="number"
placeholder="Minutes"
/>
<input
onChange={onHoursChange}
value={hours}
type="number"
placeholder="Hours"
/>
</div>
);
๐๐ป ์ด์ ์๊ฐ์ ๋ํ input ํ๊ทธ์์ ๊ฐ์ ๋ฐ์์, hourSelector
๋ก ๋๊ฒจ minuteState ๊ฐ์ผ๋ก ๋ณํ์์ผ ๋ณด์ฌ์ค ์ ์๋ค. ๊ฐ๊ฐ์ ์๊ฐ๊ณผ ๋ถ์ onChange ํจ์๋ก ๊ฐ์ ๋ณํ๋ฅผ ๊ด์ฐฐํ์ฌ์ผ ํ๋ค.
ํ๋ฉด์ ์์๋ฅผ ๋๋๊ทธํ๊ณ ์ฌ์ฉ์๊ฐ ์ํ๋ ์์น์ ๋๋ํ ์ ์๋ ๊ธฐ๋ฅ์ ์์ฝ๊ฒ ๋ง๋ค ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
Droppable
์ ๋๋๊ทธ & ๋๋์ด ๊ฐ๋ฅํ ๋ถ๋ถ์ ๋ปํ๊ณ , Draggable
์ ๋๋๊ทธ & ๋๋์ด ๊ฐ๋ฅํ ์์๋ฅผ ๋ปํ๋ค. ์ ์์ ์์ ์์๋ก ํ์๊ฐ ๋ค์ด๊ฐ ์์ด์ผ ํจ! ๐ฅ
App.tsx
const toDos = ["a", "b", "c", "d", "e", "f"];
function App() {
const onDragEnd = () => {};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Wrapper>
<Boards>
<Droppable droppableId="one">
{(magic) => (
<Board ref={magic.innerRef} {...magic.droppableProps}>
{toDos.map((toDo, index) => (
<Draggable draggableId={toDo} index={index}>
{(magic) => (
<Card
ref={magic.innerRef}
{...magic.dragHandleProps}
{...magic.draggableProps}
>
{toDo}
</Card>
)}
</Draggable>
))}
{magic.placeholder}
</Board>
)}
</Droppable>
</Boards>
</Wrapper>
</DragDropContext>
);
}
๐๐ป DragDropContext์ ํ๋ผ๋ฏธํฐ๋ก ๋๋๊ทธ์ ๋๋์ด ๋๋ฌ์ ๋ ์ํ๋ onDragEnd ํจ์๋ฅผ ๊ผญ ๋๊ฒจ์ฃผ์ด์ผ ํ๋ค. ์์ ์์๋ค์ด ํ ์ผ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ค๋ฅด๊ฒ ํจ์ ํํ๋ก ๊ฐ์ธ์ ธ ์๋ค.
๋๋๊ทธ์ ๋๋์ด ๋๋ฌ์ ๋ ์ํํ๋ ํจ์๋ก์จ ๊ธฐ์กด์ ๋ฐฐ์ด ํํ๋ฅผ ๋ฐ๊ฟ ์ฃผ์ง ์์ผ๋ฉด ์๋ ํํ ๊ทธ๋๋ก map ํจ์๋ฅผ ์คํ์ํค๊ธฐ ๋๋ฌธ์ ์์๊ฐ ๋ฐ๋์ง ์์!! ๐ ๐ปโโ๏ธ ๋ฐ๋ผ์ onDragEnd ํจ์ ๋ด์์ ๊ธฐ์กด์ ๋ฐฐ์ด์ ๊ผญ ๋ณํ์์ผ ์ฃผ์ด์ผ ํจ.
const onDragEnd = ({ draggableId, destination, source }: DropResult) => {
if (!destination) return;
setToDos((oldToDos) => {
const toDosCopy = [...oldToDos];
// 1) Delete item on source.index
console.log("Delete item on", source.index);
console.log(toDosCopy);
toDosCopy.splice(source.index, 1);
console.log("Deleted item");
console.log(toDosCopy);
// 2) Put back the item on the destination.index
console.log("Put back", draggableId, "on ", destination.index);
toDosCopy.splice(destination?.index, 0, draggableId);
console.log(toDosCopy);
return toDosCopy;
});
};
๐๐ป ๋๋๊ทธ์ ๋๋์ด ๋๋ฌ์ ๋ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ฒด๋ก ๋ฐ์์ค๊ธฐ ๋๋ฌธ์ ์ธ์๋ก ๋๋๊ทธ ๋ ์์์ ์์ด๋์ ์์์ , ๋์ฐฉ์ ์ ๋ฃ์ด์ค๋ค. ๋ง์ฝ ์์์ ๊ทธ๋๋ก์ ์์น์์ ๋๋๊ทธ์ ๋๋์ด ๋๋ฌ๋ค๋ฉด, destination์ด ์กด์ฌํ์ง ์์ ๊ฒ์ด๋ฏ๋ก ํจ์๋ฅผ ๊ทธ๋๋ก return ์์ผ์ค๋ค.
โ
๊ธฐ์กด์ ๋ฐฐ์ด์ ๊ฐ์ ธ์ ์์ง์ธ ์์๋ฅผ ์ญ์ โก๏ธ ๋์ฐฉ์ ์ index์ ์์ ์ฝ์
โก๏ธ setToDos๋ฅผ ํตํด ์๋ก์ด ๋ฐฐ์ด ์ ์ฅ