let's get IT with DAVINA πŸ’»

찜 κΈ°λŠ₯ (μœ„μ‹œλ¦¬μ‹œνŠΈ) λ³Έλ¬Έ

Project/μ™œ κ°€?

찜 κΈ°λŠ₯ (μœ„μ‹œλ¦¬μ‹œνŠΈ)

λ‹€λΉˆμΉ˜μ½”λ“œπŸ’Ž 2023. 2. 8. 22:03
  • ν˜Έν…” μΉ΄ν…Œκ³ λ¦¬ 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
              />
            ))}
)

3. κ°œλ³„ HotelCard componentμ—μ„œ ν•΄λ‹Ή 정보λ₯Ό μ΄μš©ν•΄μ„œ ν•˜νŠΈ μ±„μš°κΈ°/λΉ„μš°κΈ°

  • 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>

4. wishList page에선 μ’‹μ•„μš” 된 μƒνƒœλ§Œ 남기기

  • 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κ°’λ§Œ λ„˜κ²¨μ€˜μ„œ μœ„μ‹œλ¦¬μŠ€νŠΈ νŽ˜μ΄μ§€λŠ” ν•˜νŠΈκ°€ μ°¬ κ²ƒλ“€λ§Œ 있게됨
              />
            ))}

'Project > μ™œ κ°€?' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

scroll prevent  (0) 2023.02.17
두 λ‚ μ§œ 사이 계산  (0) 2023.02.09
KakaoMap Api 적용  (0) 2023.02.09
button count μ‘°μ •/μ œν•œ  (0) 2023.02.09
[μ™œ κ°€?] ν”„λ‘œμ νŠΈ 회고  (6) 2023.02.08
Comments