찜 기능 (위시리스트)

Davina·2023년 2월 2일
0

All Empty Study 🫥

목록 보기
12/16
  • 호텔 카테고리 list 화면에서 좋아요된 호텔이 채워진하트로 표시 필요
    → BE에서 isLike 와 같은필드명으로 구분해줘야함
  • 호텔 카테고리 list 화면에서 like가 전역으로 관리되게 되면 호텔별 좋아요 상태 표시가(한개 누르면 전체 상태가 다 바뀌게 됨) 힘드므로 개별 상태로 관리가능하도록 수정
  • 위시리스트 페이지에서는 호텔 하트 채워진상태로 표시

메인 프로젝트때의 상황
→ BE에 isLike 구분이 안되어 있었으며,
→ wishlist에선 data정보들이 있었음
⇒ 따라서, 좋아요를 눌렀는지 안눌렀는지를 판단하는것보다 위시리스트에 있는 호텔이 전체리스트의 호텔 id값과 일치할 경우 좋아요가 되어있는 상태 & 위시리스트에 없으면 좋아요가 안되어있는 상태로 구분

1. WishList data 불러오기

  • store/WishList.js
    import axios from "axios";
    import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
    import { accessToken } from "../utils/localStorage";
    
    export const getWishList = createAsyncThunk("GET_WISH", async () => {
      const wishList = await (
        await axios.get(`/member/wishlists`, {
          headers: {
            Authorization: accessToken,
          },
        })
      ).data;
      return wishList.data;
    });
    
    const initialState = [];
    
    export const WishState = createSlice({
      name: "wishstate",
      initialState,
      reducers: {},
      extraReducers: {
        [getWishList.fulfilled]: (state, { payload }) => [...payload],
      },
    });

2. 전체 호텔 리스트에서 wishlist data 불러오기

  • pages/AllProducts.jsx
    export default function AllProducts() {
    	const wish = useSelector((state) => state.Wishlist);
    	const { isLoading, error, productsList } = useAllProducts(getUrl, pathname);
    	
    	const likedHotelList = wish.map((el) => el.hotelId);
    
    	useEffect(() => {
        dispatch(getWishList());
      }, [dispatch]);
    
    return (
    	{productsList &&
                productsList.map((el) => (
                  <HotelCard
                    isLogin={isLogin}
                    key={el.hotelId}
                    id={el.hotelId}
                    title={el.hotelTitle}
                    price={el.price}
                    score={el.hotelReviewScore}
                    img={el.hotelImage}
                    reviewNum={el.reviewQuantity}
                    wish={wish}
                    isSelected={likedHotelList.includes(el.hotelId)} //wishList에 있는 hotelId값과 전체리스트페이지(productList)의 hotelid값이 같은게 있는지 찾기 => boolean
                  />
                ))}
    )
    
  • components/HotelCard.jsx
    export default function HotelCard({
      title,
      price,
      score,
      img,
      id,
      reviewNum,
      isSelected,
      isLogin,
    }) {
    
    	const handleNavigate = () => {
        navigate(`/rooms/${id}`, { state: id });
      };
    
      const dispatch = useDispatch();
      const [isLike, setIsLike] = useState(isSelected); //포함되어있으면 true(좋아요 된상태가 됨) 포함안되어있으면 false(좋아요 안된상태가 됨)
    
    const handleLike = async (id, e) => {
        e.stopPropagation();
        // 로그인 안될 시, 먼저 잡고 로그인
        if (!isLogin) {
          dispatch(modalOpen());
          return;
        }
    
        if (isLike === false) {
          try {
            await axios.post(`/member/wishlists?hotelId=${id}`, undefined, {
              headers: {
                Authorization: localStorage.getItem("accessToken"),
              },
            });
          } catch (error) {
            console.error(error);
          }
        } else {
          try {
            await axios.delete(`/member/wishlists?hotelId=${id}`, {
              headers: {
                Authorization: localStorage.getItem("accessToken"),
              },
            });
          } catch (error) {
            console.error(error);
          }
        }
        setIsLike(!isLike) //false이건 true이건 똑같이 로직 뒤집어 주는거니까 if문 끝나면 한꺼번에 처리
      };
    
      return (
        <CardBox onClick={(e) => handleNavigate(e)}>
          <ImgBox img={img}>
            <Icon onClick={(e) => handleLike(id, e)}>
    					{isLike ? <AiFillHeart className="heart" /> : <AiOutlineHeart />}
            </Icon>

3. wishlist 페이지에선 좋아요 된 상태만 남기기

  • pages/WishLists.jsx
    export default function WishLists() {
      const wish = useSelector((state) => state.Wishlist);
      const dispatch = useDispatch();
    
    	useEffect(() => {
        dispatch(getWishList());
      }, [dispatch]);
    
    	return (
    		{wish &&
                wish.map((el) => (
                  <HotelCard
                    isLogin={isLogin}
                    key={el.hotelId}
                    id={el.hotelId}
                    title={el.hotelTitle}
                    price={el.price}
                    score={el.hotelReviewScore}
                    img={el.hotelImage}
                    reviewNum={el.reviewQuantity}
                    isSelected //true값만 넘겨줘서 위시리스트 페이지는 하트가 찬 것들만 있게됨
                  />
                ))}
profile
[많을 (다) 빛날 (빈)] 빛이나는 사람이 되고 싶습니다

0개의 댓글