๐ย ์ฃผ์ ๊ธฐ๋ฅ
- ์ํ ๊ด๋ฆฌ (State)
- IntersectionObserver๋ฅผ ํ์ฉํ ์น์ ๊ฐ์ง
- ์คํฌ๋กค ๊ฐ์ง๋ก Top ๋ฒํผ ํ์
- ๋ ๋๋ง ๊ตฌ์กฐ - ๊ฐ ์น์ ์ ๊ตฌ๋ถํด์ ๋ถ๋๋ฌ์ด ์ด๋ ๊ฐ๋ฅํ๊ฒ ์ค์
<aside> ๐ฌ
const [activeSection, setActiveSection] = useState('');
const [showButton, setShowButton] = useState(false);
useEffect(() => {
const sections = document.querySelectorAll('section');
// ํน์ ์น์
์ด ํ๋ฉด์ 10% ์ด์ ๋ค์ด์ค๋ฉด ๊ฐ์ง๋๋๋ก IntersectionObserver ์ค์
const observerOptions = {
root: null,
threshold: 0.1,
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveSection(entry.target.id);
}
});
}, observerOptions);
// dom์ ํตํด ๊ฐ์ ธ์จ ์น์
์์๋ค์ ๊ด์ฐฐ ๋์์ผ๋ก ๋ฑ๋กํจ
sections.forEach((section) => {
observer.observe(section);
});
return () => {
sections.forEach((section) => observer.unobserve(section));
};
}, []);
</aside>
<aside> ๐ฌ
// ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ง์ดํธ๋ ๋ ํ ๋ฒ๋ง ์คํ๋จ (์คํฌ๋กค ๊ฐ์ง ์ค์ ์ ํ ๋ฒ๋ง ํ์ํ๋๊น)
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 340) {
setShowButton(true); // ๋ฒํผ ๋ณด์ด๊ธฐ
} else {
setShowButton(false); // ๋ฒํผ ์จ๊ธฐ๊ธฐ
}
};
// ์คํฌ๋กค ์ด๋ฒคํธ ๊ฐ์ง ์์
window.addEventListener("scroll", handleScroll);
// ์ปดํฌ๋ํธ ์ฌ๋ผ์ง ๋ ์ด๋ฒคํธ ์ ๊ฑฐ
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []); // []๋ฅผ ๋ฃ์ด์ useEffect๋ฅผ ํ ๋ฒ๋ง ์คํ์ํด
</aside>
<aside> ๐ฌ
return (
<>
<Header activeSection={activeSection} />
<main className="relative">
<IntroSection />
<section id="about">
<AboutSection />
</section>
<section id="stack">
<StackSection />
</section>
<section id="project">
<ProjectSection />
</section>
<section id="contact">
<ContactSection />
</section>
</main>
<TopButton showButton={showButton} />
</>
);
};
</aside>