diff --git a/client/src/features/CasperCustom/CasperFlipCard.tsx b/client/src/features/CasperCustom/CasperFlipCard.tsx
index e89d04df..4b7f23b7 100644
--- a/client/src/features/CasperCustom/CasperFlipCard.tsx
+++ b/client/src/features/CasperCustom/CasperFlipCard.tsx
@@ -1,3 +1,4 @@
+import { memo } from "react";
import { motion } from "framer-motion";
import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper";
import { CasperCardType } from "../CasperShowCase/TransitionCasperCards";
@@ -10,7 +11,7 @@ interface CasperFlipCardProps {
isFlipped: boolean;
}
-export default function CasperFlipCard({ size, card, isFlipped }: CasperFlipCardProps) {
+function CasperFlipCard({ size, card, isFlipped }: CasperFlipCardProps) {
return (
);
}
+
+export default memo(CasperFlipCard);
diff --git a/client/src/features/CasperShowCase/TransitionCasperCards.tsx b/client/src/features/CasperShowCase/TransitionCasperCards.tsx
index 294cd41c..4a0ee465 100644
--- a/client/src/features/CasperShowCase/TransitionCasperCards.tsx
+++ b/client/src/features/CasperShowCase/TransitionCasperCards.tsx
@@ -1,7 +1,8 @@
import { useEffect, useRef, useState } from "react";
import { motion, useAnimation } from "framer-motion";
-import { CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper";
+import { CASPER_CARD_SIZE, CASPER_SIZE_OPTION } from "@/constants/CasperCustom/casper";
import { CARD_TRANSITION } from "@/constants/CasperShowCase/showCase";
+import useLazyLoading from "@/hooks/useLazyLoading";
import { SelectedCasperIdxType } from "@/types/casperCustom";
import CasperFlipCard from "../CasperCustom/CasperFlipCard";
@@ -28,7 +29,7 @@ export default function TransitionCasperCards({
gap,
isEndCard,
}: TransitionCasperCardsProps) {
- const containerRef = useRef(null);
+ const containerRef = useRef(null);
const transitionControls = useAnimation();
const [x, setX] = useState(initialX);
@@ -55,6 +56,7 @@ export default function TransitionCasperCards({
const renderCardItem = (cardItem: CasperCardType, id: string) => {
const [isFlipped, setIsFlipped] = useState(false);
+ const { isInView, cardRef } = useLazyLoading();
const handleMouseEnter = () => {
stopAnimation();
@@ -67,18 +69,29 @@ export default function TransitionCasperCards({
};
return (
-
-
-
+
+ {isInView && (
+
+ )}
+
);
};
return (
-
{cardList.map((card) => renderCardItem(card, card.id))}
{cardList.map((card) => renderCardItem(card, `${card.id}-clone`))}
-
+
);
}
diff --git a/client/src/hooks/useLazyLoading.ts b/client/src/hooks/useLazyLoading.ts
new file mode 100644
index 00000000..6d612e41
--- /dev/null
+++ b/client/src/hooks/useLazyLoading.ts
@@ -0,0 +1,30 @@
+import { useEffect, useRef, useState } from "react";
+
+export default function useLazyLoading() {
+ const [isInView, setIsInView] = useState(false);
+ const cardRef = useRef(null);
+
+ useEffect(() => {
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting) {
+ setIsInView(true);
+ observer.disconnect();
+ }
+ },
+ { threshold: 0, root: document.body }
+ );
+
+ if (cardRef.current) {
+ observer.observe(cardRef.current);
+ }
+
+ return () => {
+ if (cardRef.current) {
+ observer.unobserve(cardRef.current);
+ }
+ };
+ }, [cardRef]);
+
+ return { isInView, cardRef };
+}