From 63b6b1a85afa74d6125a4ea9988f9cf639fca02c Mon Sep 17 00:00:00 2001 From: "MTG\\mtg09" <50504183+MTG2000@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:39:08 +0400 Subject: [PATCH] perf: improve images loading in carousel --- .../ProjectsSelect/ProjectsSelect.tsx | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/v2/src/Components/ProjectsSelect/ProjectsSelect.tsx b/v2/src/Components/ProjectsSelect/ProjectsSelect.tsx index d39db5a..506b4d8 100644 --- a/v2/src/Components/ProjectsSelect/ProjectsSelect.tsx +++ b/v2/src/Components/ProjectsSelect/ProjectsSelect.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { projects } from "./projects"; import { serifText } from "@/assets/fonts"; import Image from "next/image"; @@ -13,30 +13,14 @@ interface Props { } export default function ProjectsSelect({ excludeProjects }: Props) { - const [emblaRef, empblaApi] = useEmblaCarousel(); + const [emblaRef] = useEmblaCarousel(); const router = useRouter(); + const projectsContainerRef = useRef(null); + const isOnScreen = useOnScreen(projectsContainerRef); const [openProject, setOpenProject] = useState< (typeof projects)[number] | null >(null); - const [slidesInView, setSlidesInView] = useState([]); - - useEffect(() => { - if (!empblaApi) return; - - const updateNextSlidePriority = () => { - const slidesInView = empblaApi.slidesInView(); - setSlidesInView(slidesInView); - }; - - empblaApi.on("init", updateNextSlidePriority); - empblaApi.on("slidesInView", updateNextSlidePriority); - - return () => { - empblaApi.off("init", updateNextSlidePriority); - empblaApi.off("slidesInView", updateNextSlidePriority); - }; - }, [empblaApi]); const options = projects.filter( (project) => !excludeProjects?.includes(project.slug) @@ -59,7 +43,7 @@ export default function ProjectsSelect({ excludeProjects }: Props) { return (
-
    +
      {options.map((option, idx) => (
@@ -126,3 +111,29 @@ export default function ProjectsSelect({ excludeProjects }: Props) {
); } + +function useOnScreen( + ref: React.MutableRefObject, + rootMargin = "0px" +) { + const [isVisible, setIsVisible] = useState(false); + useEffect(() => { + const elementToObserve = ref?.current; + + if (!elementToObserve) return; + + const observer = new IntersectionObserver( + ([entry]) => setIsVisible(entry.isIntersecting), + { rootMargin } + ); + observer.observe(elementToObserve); + + return () => { + if (!elementToObserve) return; + + observer.unobserve(elementToObserve); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [rootMargin]); + return isVisible; +}