I am trying to navigate(scroll) the one pager with onClick function in header, and at the same time have functionality to change navlink active classname while scrolling the page. When I reach the scroll position of About section, navlink About should get active class.
The problem is I get the scroll to work but then I can't use navlink onClick function. It changes the state for milisecond and goes back to the previous.
I need instructions to achieve this and I guess there is a solution but I did not think it up very well. If you can redirect me to a tutorial for achieving this functionality or tell me what should I do to make it correctly.
Thank you very much!
App.js
import React, { useEffect, useRef, useState } from "react";
import Header from "./components/Header";
import "./App.scss"
import About from "./sections/About";
import Home from "./sections/Home";
import Projects from "./sections/Projects";
function App() {
const [scrollState, setScrollState] = useState("home")
const homeRef = useRef(null);
const aboutRef = useRef(null);
const projectsRef = useRef(null);
const handleNavScroll = (e) => {
setScrollState(e)
}
const handleScroll = () => {
const homeOffset = homeRef.current.offsetTop;
const aboutOffset = aboutRef.current.offsetTop;
const projectsOffset = projectsRef.current.offsetTop;
const scrollPosition = window.scrollY;
if (
scrollPosition >= homeOffset &&
scrollPosition < aboutOffset &&
scrollState !== "home"
) {
setScrollState("home");
} else if (
scrollPosition >= aboutOffset &&
scrollPosition < projectsOffset &&
scrollState !== "about" &&
scrollState !== "projects"
) {
setScrollState("about");
} else if (
scrollPosition > projectsOffset - 200 &&
scrollState !== "projects" &&
scrollState !== "home"
) {
setScrollState("projects");
}
};
useEffect(() => {
const vh = window.innerHeight * 0.08;
if (scrollState === "home") {
homeRef.current.scrollIntoView({ behavior: "smooth", top: homeRef - vh, });
const CurrentScrollLocation = homeRef.current.scrollTop;
homeRef.current.scrollTo({ top: CurrentScrollLocation - vh })
} else if (scrollState === "about") {
aboutRef.current.scrollIntoView({ behavior: "smooth" });
} else if (scrollState === "projects") {
projectsRef.current.scrollIntoView({ behavior: "smooth" });
}
window.addEventListener("scroll", handleScroll);
return () => {
window.addEventListener("scroll", handleScroll);
}
}, [scrollState])
return (
<div className="App">
<Header navClick={handleNavScroll} active={scrollState} />
<main>
<Home homeRef={homeRef} aboutRef={aboutRef} projectsRef={projectsRef} />
<About homeRef={homeRef} aboutRef={aboutRef} projectsRef={projectsRef} />
<Projects homeRef={homeRef} aboutRef={aboutRef} projectsRef={projectsRef} />
</main>
</div>
);
}
export default App;
Header.jsx
import React from 'react'
import "./Header.scss"
function Header({ navClick, active }) {
return (
<header>
<ul className='navbar'>
<li
className={active === "home" ? "navitem active" : "navitem"}
onClick={() => {navClick("home")}}>ZBIRKE PJESAMA</li>
<li
className={active === "about" ? "navitem active" : "navitem"}
onClick={() => {navClick("about")}}>O MENI</li>
<li
className={active === "projects" ? "navitem active" : "navitem"}
onClick={() => {navClick("projects")}}>PROJEKTI</li>
</ul>
</header>
)
}
export default Header
I tried doing it using the isNavigating state but failed and I got messed up in my head and could not find the way to properly update isNavigating state and either run onClick or Scroll depending on the state.