const [checkedItemIds, setCheckedItemIds] = useRecoilState(checkedCartItemIdsState(cartItemIds));
선택된 장바구니 아이템의 id를 담은 배열인 checkedItemIds
를 전역 상태로 만들어주었다. 처음 렌더링 시 모두 선택된 것을 기본 값으로 주고 싶어서 장바구니 목록에 있는 아이템의 아이디를 인자로 받아 초기화할 수 있도록 atomFamily
로 만들어줬다.
export default function CartItem({ cartItemInfo, checkedItemIds, setCheckedItemIds }: Props) {
const { name, price, imageUrl } = cartItemInfo.product;
const { updateProductQuantity, deleteFromCart } = useCart(cartItemInfo.product);
const toggleCheckbox = (id: number) => {
if (checkedItemIds.includes(id)) {
setCheckedItemIds((prev) => prev.filter((itemId) => itemId !== id));
return;
}
setCheckedItemIds((prev) => [...prev, id]);
};
const deleteCartItem = () => {
setCheckedItemIds((prev) => prev.filter((itemId) => itemId !== cartItemInfo.id));
deleteFromCart();
};
...
}
checkedItemIds
배열을 CartItem
컴포넌트로 전달하여 체크박스 클릭 시 checkedItemIds
에 아이템이 있다면 checkedItemIds
배열에서 삭제, 없다면 배열에 추가하는 방식으로 toggleCheckbox
를 구현했다. 다시 말해, 해당 아이템이 선택 되었는지 여부를 배열 탐색을 통해 알 수 있고 조작할 수 있도록 구현했다!
// selector 내부에 있는 장바구니 목록 fetch 로직(기존로직)
export const currentCartListState = selector<CartItemInfo[]>({
key: 'currentCartList',
get: async ({ get }) => {
const cartList = get(cartListState); // selector에 의존성을 추가하기 위한 코드
if (cartList.length > 0) return cartList;
const res = await fetch(CART_BASE_URL);
if (!res.ok) throw new Error('장바구니 목록을 불러올 수 없습니다.');
const currentCartList = await res.json();
return currentCartList;
},
});
recoil
의 selector
내부에서 장바구니 목록을 fetch
해오는 로직을 작성했다. 리코일 셀렉터 내부에서 비동기 로직을 작성함으로써 suspense
도 쉽게 적용할 수 있었기 때문에 만족하고 있던 차에 fetch
로직은 selector
밖으로 분리하라는 피드백을 받았다.
리코일 공식문서에 나온 예제와 내 로직의 차이가 무엇이고 내 로직은 무엇이 잘못된 것인지 궁금해서 아래와 같이 질문을 남겼고 그에 대한 피드백을 받으며 selector
가 순수함수로 동작해야하는 이유에 대해 다시 한번 생각해볼 수 있었다.
질문1
답변1
질문2
답변2
Be the best version of you!