codeStates front-end/React

[React] styled-components - card , dummydata ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ์— ๋ฐ์ดํ„ฐ ๋„ฃ๊ธฐ

ํ™˜ํ…Œํฌ 2023. 5. 16. 00:32
๋ฐ˜์‘ํ˜•

 

 

 

 

 

๐Ÿ“Œ dummydata ๊ตฌํ˜„

 

 

DummyData.js

 

export const campgrounds = {
  data: [
    {
      productId: 2,
      productName: "์บ ํ•‘์žฅ2",
      address: "ํ•œ๊ฐ• ์–ด๋”˜๊ฐ€2",
      location: "์„œ์šธ2",
      content: "์บ ํ•‘์žฅ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.2",
      capacity: 10,
      cancellationDeadline: "2023-05-03T10:00:00",
      productPrice: 30000,
      productPhone: "010-1234-1111",
      latitude: null,
      longitude: null,
      deleted: false,
      createdAt: "2023-05-10T09:24:02.995997",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:24:02.995997",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 1,
      productName: "new์บ ํ•‘์žฅ",
      address: "newํ•œ๊ฐ• ์–ด๋”˜๊ฐ€",
      location: "new์„œ์šธ",
      content: "new์บ ํ•‘์žฅ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 3,
      productName: "์„œ์šธํŠน๋ณ„์‹œ",
      address: "์„œ์šธํŠน๋ณ„์‹œ",
      location: "์„œ์šธํŠน๋ณ„์‹œ",
      content: "์˜ฌํ…Œ๋ฉด์™€๋ผ.",
      capacity: 10000,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 4,
      productName: "๋Œ€๊ตฌ๊ด‘์—ญ์‹œ",
      address: "๋Œ€๊ตฌ๊ด‘์—ญ์‹œ",
      location: "๋Œ€๊ตฌ๊ด‘์—ญ์‹œ",
      content: "๋Œ€๊ตฌ๊ด‘์—ญ์‹œ๋ฅผ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 5,
      productName: "๋Œ€์ „๊ด‘์—ญ์‹œ",
      address: "๋Œ€์ „๊ด‘์—ญ์‹œ",
      location: "๋Œ€์ „๊ด‘์—ญ์‹œ",
      content: "๋Œ€์ „๊ด‘์—ญ์‹œ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 6,
      productName: "๊ด‘์ฃผ๊ด‘์—ญ์‹œ",
      address: "๊ด‘์ฃผ๊ด‘์—ญ์‹œ",
      location: "๊ด‘์ฃผ๊ด‘์—ญ์‹œ",
      content: "๊ด‘์ฃผ๊ด‘์—ญ์‹œ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 7,
      productName: "์šธ์‚ฐ๊ด‘์—ญ์‹œ",
      address: "์šธ์‚ฐ๊ด‘์—ญ์‹œ",
      location: "์šธ์‚ฐ๊ด‘์—ญ์‹œ",
      content: "์šธ์‚ฐ๊ด‘์—ญ์‹œ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 8,
      productName: "์ธ์ฒœ๊ด‘์—ญ์‹œ",
      address: "์ธ์ฒœ๊ด‘์—ญ์‹œ ์–ด๋”˜๊ฐ€",
      location: "์ธ์ฒœ๊ด‘์—ญ์‹œ",
      content: "์ธ์ฒœ๊ด‘์—ญ์‹œ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 9,
      productName: "๋ถ€์‚ฐ๊ด‘์—ญ์‹œ",
      address: "๋ถ€์‚ฐ๊ด‘์—ญ์‹œ ์–ด๋”˜๊ฐ€",
      location: "๋ถ€์‚ฐ๊ด‘์—ญ์‹œ",
      content: "๋ถ€์‚ฐ๊ด‘์—ญ์‹œ ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
    {
      productId: 10,
      productName: "์ œ์ฃผํŠน๋ณ„์ž์น˜๋„ ",
      address: "์ œ์ฃผํŠน๋ณ„์ž์น˜๋„  ์–ด๋”˜๊ฐ€",
      location: "์ œ์ฃผํŠน๋ณ„์ž์น˜๋„ ",
      content: "์ œ์ฃผํŠน๋ณ„์ž์น˜๋„  ๋นŒ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
      capacity: 10,
      cancellationDeadline: "2023-05-05T00:35:17",
      productPrice: 30000,
      productPhone: "010-1234-5337",
      latitude: 37.5,
      longitude: 40.5,
      deleted: false,
      createdAt: "2023-05-10T09:21:24.770742",
      createdBy: "name",
      modifiedAt: "2023-05-10T09:21:46.344073",
      modifiedBy: "name",
      imageUrl: "http://~",
      memberId: 1,
    },
  ],
  pageInfo: {
    page: 1,
    size: 10,
    totalElements: 10,
    totalPages: 1,
  },
};

export const dummyUsers = [
  {
    memberId: 1,
    name: "๊น€์ฝ”๋”ฉ",
    email: "example@gmail.com",
    createdAt: "2023-05-10T00:56:10.906617",
    modifiedAt: "2023-05-10T00:56:10.906631",
    createdBy: "example@gmail.com",
    modifiedBy: "example@gmail.com",
    phone: "010-1111-2222",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: false,
    businessRegistrationNumber: null,
  },
  {
    memberId: 2,
    name: "์กฐ์ฝ”๋”ฉ",
    email: "example2@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example2@gmail.com",
    modifiedBy: "example2@gmail.com",
    phone: "010-2222-3333",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 3,
    name: "์ฝ”์ฝ”๋”ฉ",
    email: "example3@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example3@gmail.com",
    modifiedBy: "example3@gmail.com",
    phone: "010-3333-3333",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 4,
    name: "์˜ค์ฝ”๋”ฉ",
    email: "example4@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example4@gmail.com",
    modifiedBy: "example4@gmail.com",
    phone: "010-0000-0000",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 5,
    name: "์ตœ์ฝ”๋”ฉ",
    email: "example5@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example5@gmail.com",
    modifiedBy: "example5@gmail.com",
    phone: "010-5555-5555",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 6,
    name: "๋”ฉ์ฝ”๋”ฉ",
    email: "example6@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example6@gmail.com",
    modifiedBy: "example6@gmail.com",
    phone: "010-6666-6666",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 7,
    name: "๋ฐ•์ฝ”๋”ฉ",
    email: "example7@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example7@gmail.com",
    modifiedBy: "example7@gmail.com",
    phone: "010-7777-7777",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 8,
    name: "ํ•˜์ฝ”๋”ฉ",
    email: "example8@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example8@gmail.com",
    modifiedBy: "example8@gmail.com",
    phone: "010-1234-4321",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 9,
    name: "๊ฐ•์ฝ”๋”ฉ",
    email: "example9@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example9@gmail.com",
    modifiedBy: "example9@gmail.com",
    phone: "010-9999-9999",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
  {
    memberId: 10,
    name: "์œ ์ฝ”๋”ฉ",
    email: "example10@gmail.com",
    createdAt: "2023-05-10T00:56:55.746517",
    modifiedAt: "2023-05-10T00:56:55.746559",
    createdBy: "example10@gmail.com",
    modifiedBy: "example10@gmail.com",
    phone: "010-1010-1010",
    reward_points: 0,
    memberStatus: "MEMBER_ACTIVE",
    memberShip: "BASIC",
    birthDate: "2000-01-01",
    usageCount: 0,
    favoriteId: 1,
    isEmailVerified: true,
    isSellerVerifed: true,
    businessRegistrationNumber: "123-12-12345",
  },
];

export const dummyChats = [
  {
    id: 1,
    customer: false,
    content: "ํฌํฌํฌํฌํ‚„ํฌํฌํฌํฌํฌํฌํฌ",
  },
  {
    id: 2,
    customer: true,
    content: "ํฌํฌํฌํฌํ‚„ํฌํฌํฌํฌํฌํฌํฌ",
  },
  {
    id: 3,
    customer: true,
    content: "ํฌํฌํฌํฌํ‚„ํฌํฌํฌํฌํฌํฌํฌ",
  },
  {
    id: 4,
    customer: true,
    content: "ํฌํฌํฌํฌํ‚„ํฌํฌํฌํฌํฌํฌํฌ",
  },
];

 

card2.jsx

 

import styled from "@emotion/styled";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPhone, faMap, faUser } from "@fortawesome/free-solid-svg-icons";
import { useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { useState } from "react";

const Container = styled.div`
  background-color: transparent;
  width: 250px;
  height: 350px;
  perspective: 1000px;
  border-radius: 10px;
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  transition: border-radius 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);

  &:hover .inner {
    transform: rotateY(180deg);
  }
`;

const Inner = styled.div`
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.6s;
  transform-style: preserve-3d;
`;

const Front = styled.div`
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 2em;
  backface-visibility: hidden;
  background-color: ${(props) =>
    props.isDark ? "var(--white-50)" : "var(--white)"};
  color: var(--black-700);
  border: none;
  display: flex;
  flex-direction: column;
  align-items: center;
`;

const Img = styled.div`
  display: flex;
  align-items: center;
  border: none;
  border-radius: 30px;
  width: 100%;
  height: 200px;
  background-image: url(${(props) => props.bgphoto});
  background-size: cover;
  background-position: center;
  border-bottom: none;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
`;

const Name = styled.div`
  margin-bottom: 10px;
  font-size: 18px;
`;

const Selection = styled.div`
  margin: 30px 0 10px 0;
  font-size: 13px;
  /* color : #DF2E38; */
`;

const Price = styled.div`
  /* margin: 30px 0 10px 0; */
  font-size: 25px;
`;

const Back = styled.div`
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 2em;
  backface-visibility: hidden;
  background-color: ${(props) =>
    props.isDark ? "var(--white-50)" : "var(--white)"};
  border: none;
  transform: rotateY(180deg);
  padding: 11px;
`;

const Info = styled.div`
  width: 100%;
  height: 100%;
  letter-spacing: 1px;
  display: grid;
  grid-template-rows: 3fr 1fr;
  align-items: center;
  justify-content: center;
  text-align: center; // ์ถ”๊ฐ€
`;

const Descriptions = styled.div`
  width: 250px;
  padding: 0 10px;
  /* height: 300px; */
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center; // ์ถ”๊ฐ€
  color: var(--black-700);
`;

const Description = styled.div`
  font-size: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center; // ์ถ”๊ฐ€
`;

const Icons = styled.div`
  display: flex;
  justify-content: space-around;
  align-items: center;
  color: var(--black-700);
  margin-bottom: 100px;
`;

const Icon = styled(FontAwesomeIcon)`
  font-size: 25px;
  cursor: pointer;
`;

const loremIpsum = "์ง€๊ธˆ ๋ฐ”๋กœ ์˜ˆ์•ฝํ•˜์„ธ์š”!";

export default function Card2({ campground }) {
  const isDark = useSelector((state) => state.modeReducer);
  const [infoType, setInfoType] = useState(null);

  const handleInfoType = (clickedType) => {
    setInfoType((prev) => clickedType);
  };

  const getInfo = (type) => {
    switch (type) {
      case "seller":
        return `ํŒ๋งค์ž: ์ˆ˜์ •ํ•„์š”!`;
      case "call":
        return `์•ˆ์‹ฌ๋ฒˆํ˜ธ: ${campground.productPhone}`;
      case "location":
        return `์œ„์น˜: ${campground.location}`;
      default:
        return campground.content;
    }
  };

  return (
    <Container>
      <Inner className="inner">
        <Front isDark={isDark}>
          <Img
            bgphoto={
              campground.imageUrl === "http://~"
                ? "https://yeyak.seoul.go.kr/cmsdata/web_upload/svc/20230329/1680050914280HZAYFX8GLLMTVZI2H6BD0WGPV_IM02.jpg"
                : campground.imageUrl
            }
          />
          <Selection>
            {campground.capacity},{campground.productPrice}
          </Selection>
          <Name>{campground.productName}</Name>
          <Price>{campground.productPrice}</Price>
        </Front>
        <Back isDark={isDark}>
          <Info>
            <Link to={`/${campground.id}`}>
              <Descriptions isDark={isDark}>
                <Description>{getInfo(infoType)}</Description>
              </Descriptions>
            </Link>
            <Icons isDark={isDark}>
              <Icon onClick={() => handleInfoType("seller")} icon={faUser} />
              <Icon onClick={() => handleInfoType("call")} icon={faPhone} />
              <Icon onClick={() => handleInfoType("location")} icon={faMap} />
            </Icons>
          </Info>
        </Back>
      </Inner>
    </Container>
  );
}

 

 

Main.JSX

 

 

import styled from "@emotion/styled";
import { useSelector } from "react-redux";
import { campgrounds } from "../Dummy/DummyDatas";
import { useEffect, useRef, useState } from "react";
import Card2 from "../Components/Card2";
import { FaChevronUp } from "react-icons/fa";

const Loader = styled.h1`
  font-size: 50px;
  font-weight: bold;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const Container = styled.main`
  max-width: 1200px;
  margin: 0 auto;
  width: 100%;
  height: auto;
  display: grid;
  grid-template-columns: 1fr;
  @media screen and (min-width: 900px) {
    grid-template-columns: repeat(2, 1fr);
  }
  @media screen and (min-width: 1100px) {
    grid-template-columns: repeat(3, 1fr);
  }
  @media screen and (min-width: 1300px) {
    grid-template-columns: repeat(4, 1fr);
  }

  gap: 20px;
  justify-items: center;
  padding: 50px 0;
  padding-top: 200px;
`;

const ContextArea = styled.div`
  width: 100%;
  margin-top: 50px;
  position: absolute;
  padding: 35px 0;
  top: 0;
  left: 0;
`;

const Title = styled.h2`
  margin-left: 150px !important;
  font-family: "Noto Sans KR", sans-serif;
  color: ${(props) => (props.isDark ? "var(--white-50)" : "var(--black-700)")};
`;

const ScrollBtn = styled.div`
  width: 120px;
  height: 70px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto;
`;

const TempWrapper = styled.div`
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;

// ๊ด€์ธก์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜
const options = {
  root: null,
  rootMargin: "0px",
  threshold: 1.0,
};

export default function Main() {
  const isDark = useSelector((state) => state.modeReducer);
  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  // ํƒ€๊ฒŸ ์š”์†Œ ์ง€์ •
  let containerRef = useRef(null);

  useEffect(() => {
    (async () => {
      setIsLoading((prev) => true);

      // ๋‚˜์ค‘์— ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•จ
      setData((prev) => [...campgrounds.data]);

      setIsLoading((prev) => false);
    })();
  }, []);

  // ๋ฌดํ•œ ์Šคํฌ๋กค์„ ์œ„ํ•œ useEffect
  useEffect(() => {
    (async () => {
      const observer = new IntersectionObserver(([entry]) => {
        if (entry.isIntersecting) {
          // ๋ฐ์ดํ„ฐ ๋” ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
        }
      }, options);

      if (containerRef.current) {
        observer.observe(containerRef.current);
      }

      return () => {
        observer.disconnect();
      };
    })();
  }, [containerRef]);

  return isLoading ? (
    <Loader>isLoading...</Loader>
  ) : (
    <>
      <ContextArea isDark={isDark}>
        <Title isDark={isDark}>์ง€๊ธˆ ๋‹น์žฅ ์บ ํ•‘์„ ๋– ๋‚˜๋ณด์„ธ์š”.โ›บ</Title>
      </ContextArea>
      <Container>
        {data.map((campground) => (
          <Card2 key={campground.id + ""} campground={campground} />
        ))}
      </Container>
      <ScrollBtn onClick={() => window.scrollTo(0, 0)} ref={containerRef}>
        <FaChevronUp size={40} />
      </ScrollBtn>
    </>
  );
}

 

 

์‹คํ–‰ํ™”๋ฉด

 

 

๋ฐ˜์‘ํ˜•