๋ง๋ค์ด๋ ๊ณผ์ ์ปค๋ฆฌํ๋ผ์ ์ฐฌ์ฐฌํ ๋ค์ ๋ณด๋ค๊ฐ. ์ด๋ผ ์ด๊ฑฐ ํฌ๋๋ฉ์ดํธ ์๋๊ฐ?
ํด์ GDSC ์คํฐ๋ ๊ธฐ๊ฐ ๋์ ํฌ๋๋ฉ์ดํธ ํด๋ก ์ฝ๋ฉ ํ๋ก์ ํธ๋ฅผ ์์ํด๋ณด๊ธฐ๋ก.
ํด๋ก ์ฝ๋ฉ์ธ ๋งํผ ์ต๋ํ ๋๊ฐ์ด ์คํ์ผ์ ๋ฃ์ผ๋ ค ๋ ธ๋ ฅํ๋ค. ๊ฐ๊ณ ์๋ ์ฐ์ธ๋ฆฌํ ๊ธ๊ผด์ ๋ช๊ฐ ๋ฃ์ด๋ดค๋๋ฐ, ํ๋ฆฌํ ๋ค๋์๋ค. ์ข์ํ๋ ํฐํธ์ผ. ๊ทธ ์ธ์ ์ด๋ฏธ์ง๋ ์์ด์ฝ ๋ฑ์ ๊ฐ๋ฐ์๋๊ตฌ ๋คํธ์ํฌํญ์์ ๊ฐ์ ธ์ค๊ฑฐ๋ ํผ๊ทธ๋ง์์ ์ง์ ๋ง๋ค์ด svg๋ก ๋ด๋ณด๋ด ์ฌ์ฉํ๋ค.
์ฝ๋๋ฅผ ์ง๊ธฐ์ ์์ ์ปดํฌ๋ํธ ๊ตฌ์กฐ๋ฅผ ์ด๋ป๊ฒ ์งค์ง์ ๋ํด์ ๊ณ ๋ฏผ์ ๊ฝค ์ค๋ ํ์๋ค. ์ค์ ํฌ๋๋ฉ์ดํธ๋ฅผ ๋ณด๋ฉด ๋๋๊ทธ์ค ๋๋์ผ๋ก ํฌ๋๋ฅผ ์ฎ๊ฒจ ์์๋ฅผ ๋ฐ๊ฟ ์ ์๊ฒ ๋์ด ์๋ค. ์ฌ์ง์ด ๋ค๋ฅธ ์นดํ
๊ณ ๋ฆฌ๋ก๋!
ํ์ง๋ง - ์นดํ
๊ณ ๋ฆฌ๋ณ ํฌ๋- -์นดํ
๊ณ ๋ฆฌ๋ณ ํฌ๋-
์ด๋ ๊ฒ ๋ถ๋ฆฌํด๋์ผ๋ฉด ๋์ค์ ๋๋๊ทธ์ค๋๋์ ๊ตฌํํ ๋ ๋ค๋ฅธ ์นดํ
๊ณ ๋ฆฌ๋ก ์ด๋์ด ์๋ ๊ฒ ๊ฐ์๋ค. ํต์ผ๋ก ๋ฐฐ์ด๋ก ์ฌ์ฉํด์ผํ๋ ์ถ์์ง๋ง... ์๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ ์ผ๋จ์ ๋ ์ค๋ฅด๋ ๋๋ก ๊ฐ์ฅ ์ง๊ด์ ์ธ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ค.
const Feed = () => {
const categories = useRecoilValue(categoryState);
return (
<Wrapper>
<div>Feed</div>
<List>
{categories.map((category) => (
<FeedItemList category={category} key={category.label} />
))}
</List>
</Wrapper>
);
};
export default Feed;
์นดํ
๊ณ ๋ฆฌ์ ๋ฐฐ์ด์ ๊ฐ๊ณ ์์ ๊ฐ ์นดํ
๊ณ ๋ฆฌ๋ง๋ค์ ํฌ๋๋ฆฌ์คํธ๋ฅผ map
์ผ๋ก ๋ณด์ฌ์ฃผ๋๋ก ํ๋ค.
const FeedItemList = ({ category }: { category: ICategory }) => {
const items = useRecoilValue(todoSelector(category.label));
const [open, setOpen] = useState<boolean>(false);
return (
<>
<CategoryButton category={category} setOpen={setOpen} />
{items.map((item) => (
<TodoItem item={item} key={item.id} />
))}
{open && <InputForm category={category} setOpen={setOpen} />}
</>
);
};
export default FeedItemList;
๊ฐ ์นดํ ๊ณ ๋ฆฌ๋ณ ํผ๋ ์ปดํฌ๋ํธ ์์์ ์นดํ ๊ณ ๋ฆฌ ์์ ์ํ๋ ํฌ๋ ๋ชฉ๋ก๋ค์ ๊ฐ์ง๊ณ ์จ๋ค. recoil์ selector๋ฅผ ์ฒ์ ์จ๋ณด์๋ค.
recoil selector
export const todoSelector = selectorFamily<ITodoItem[], string>({
key: 'todoSelector',
get:
(categoryName: string) =>
({ get }) =>
get(todoState).filter((todo) => todo.category.label === categoryName),
});
selector๋ ์์ํจ์์ด๋ค. getํจ์์์๋ RecoilValueReadOnly
๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค๊ณ ํจ. ํจ์๋ฅผ ํ๋ ๋ ๊ฐ์ธ์ ์ธ์๋ฅผ ๋๊ฒจ ์ค ์ ์๋ค. ์นดํ
๊ณ ๋ฆฌ ์ด๋ฆ์ ๋ฐ์์์ ํด๋น ์นดํ
๊ณ ๋ฆฌ์ ํด๋นํ๋ ํฌ๋๋ง filter
๋ก ๊ฐ์ ธ์ฌ ์ ์๋๋ก ํ๋ค.
๊ตฌํํ ๋ด์ฉ์ ์๋์ ๊ฐ๋ค. ์ด๋ฒ์ฃผ ๊ณผ์ ๋ ์ ๋ฒ ์ฃผ์ ๋ฐ๋๋ผ JS๋ก ๋ง๋ค์๋ ํฌ๋๋ฆฌ์คํธ๋ฅผ ๋ฆฌ์กํธ๋ฅผ ์ด์ฉํด ๋ง๋ค์ด๋ณด๋ ๊ณผ์ ์๋ค. ํฌ๋๋ฉ์ดํธ์์ ํฌ๋๋ฅผ ์ฒดํฌํ๋ ๋ถ๋ถ, ๊ทธ๋ฌ๋๊น Feed ๋ถ๋ถ๋ง ๋ง๋ค์ด๋ณด์๋ค. ๋ช์๊ฐ ๋ด์ ๋ด์ผํด์ ๋ ๋ฆผ์ผ๋ก ์ง ์ฝ๋๋ผ ๋๋์ ์ธ ๋ฆฌํฉํ ๋ง์ด ํ์ํ๋ค. ํนํ ์ํ๊ด๋ฆฌํ๋ ๊ตฌ์กฐ๋ฅผ ์ฒ์๋ถํฐ ๋ค์ ์๊ฐํด์ผํ ๊ฒ ๊ฐ๋ค.
ํฌ๋ ์์ฑํ๊ธฐ
ํฌ๋ ์ฒดํฌํ๊ธฐ ํ ๊ธ
ํฌ๋ ์ญ์ ํ๊ธฐ
๋ฑ ํค์ฆ์์ ์ผ๋ react-spring-bottom-sheet ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค. ๋ฐํ ์ํธ ์ปดํฌ๋ํธ๊ฐ ๋งค ํฌ๋์์ดํ ์ปดํฌ๋ํธ์ ๋ค์ด๊ฐ๋๋ฐ, ํฌ๋์์ดํ ์ปดํฌ๋ํธ๊ฐ ์ญ์ ๋๋ฉด์ ๋ฐํ ์ํธ๊ฐ ํ๋ฒ์ ๋ ์ฌ๋ผ์ง๋ ํ์์ด ์์์. ๋ฐํ ์ํธ๋ฅผ ๋ ์์์ ์ ์ญ์ผ๋ก ๋๊ณ ์ฌ์ฉํ๋ฉด ๋ ๊ฒ ๊ฐ์๋ฐ, ๊ทธ๋ผ ์ํ๊ด๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๋ฏ์ด๊ณ ์ณ์ผํ ๊ฒ ๊ฐ์์.. ์ผ๋จ ๋ฐ์ฐฝ๊ณ ๋ง ๋ถ์ฌ๋จ๋ค.
const handleDeleteTodo = () => {
onDismiss();
setTimeout(() => onDeleteTodo(), 300);
};
๋ฐํ ์ํธ๊ฐ ์์ ํ ๋ด๋ ค๊ฐ ๋ค์์ ํฌ๋๊ฐ ์ฌ๋ผ์ง๋๋ก ํ๋ค.
์ปค๋ฆฌํ๋ผ๋ง๋ค ์๋ํ๋ ๋ด์ฉ์ด ์๊ณ ๊ฐ ๊ณผ์ ์์ ์ฌ์ฉํ๊ณ ์ ํ๋ ๊ธฐ์ ๋ค์ด ์์ง๋ง ๊ตฌํ์ ๊ธ๊ธํด์ ํ๋๋๋ก ์ต์ํ ์คํ์ผ๋ก ์ฝ๋๋ฅผ ์๋ค. '์ฒ์์ state์ props๋ง์ ์ด์ฉํด์ ๊ด๋ฆฌํ๋ค๊ฐ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด ์ํ๊ด๋ฆฌํ๋ ๊ณผ์ '์ ๊ธฐ๋กํ๊ณ ๋ฉค๋ฒ๋ค๊ณผ๋ ๊ณต์ ํ๋๊ฒ ์๋ ๋ชฉํ์๋๋ฐ, ์์ฝ๋ค.
[Week2] ๋ฆฌ์กํธ ์์ํ๊ธฐ