Making NavBar Icon change Colour when respective component is in view- React

73 Views Asked by At

Hi i'm making a single page portfolio website as practice for React. I have an index with multiple components which are 100vh sections. My nav bar has 4 icons which are Font Awesome icons that represent the 4 sections of the single page app. What I am trying to achieve is when I am on the home section the home icon will have a different colour and then as i scroll from one section to the next their respective icons in the nav bar change to show which section the user is in.

I have already tried using Framer Motions useInView hook, useRef Hook and having a piece of state inside the index which was going to keep a string (name of component in view) which i passed down to the nav bar and had a conditional which detirmined the styling of the icons based on the value of that string(i.e. home, about, contact etc)

`export default function Home() {
  const [inView, setInView] = useState("");

  const homeSection = useRef(null);
  const aboutSection = useRef(null);
  const workSection = useRef(null);
  const contactSection = useRef(null);
  const isInView = useInView(homeSection);

  useEffect(() => {
    if (inView === "home") {
      console.log(inView);
    } else {
      console.log("nope");
    }
  }, [inView]);

  return (
    <>
      <div
        className="bg-[radial-gradient(ellipse_at_top_right,_var(--tw-gradient-stops))]
                             from-purple-600 via-violet-900 to-black flex flex-col "
      >
        <Navbar viewed={inView} />
        <div ref={homeSection} {...(isInView ? () => setInView("home") : "")}>
          <Banner />
        </div>
        <div ref={aboutSection}>
          <About />
        </div>
        <div ref={workSection}>
          <Work />
        </div>
        <div ref={contactSection}>
          <Contact />
        </div>
      </div>
    </>
  );
}

`

I have tried reading documentation but I cant find anything that i personally understand that well with my level of knowledge. Im not sure if maybe i need to have these refs inside each component or having those div wrappers around will suffice. Either way, it looks like the state "inView" is never getting set because the console log from the us

type here

eEffect always prints nope.

Unfortunately my react skills arent as good as I was hoping they were!

1

There are 1 best solutions below

2
On

You can use IntersectionObserver API to detect whether a certain section is in view or not and based on that you can maintain a state which keeps track of active section. Then based on that state, you can change the color.

useEffect(() => {
  const homeObserver = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        // element is visible
        setActiveRoute("home");
      } else {
        // element is hidden
      }
    });
  });

  homeObserver.observe(homeSection.current);
  const aboutObserver = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        // element is visible
        setActiveRoute("about");
      } else {
        // element is hidden
      }
    });
  });

  aboutObserver.observe(aboutSection.current);
  ...code for other sections
  // clean up function to disconnect observer when component unmounts
  return () => {
    homeObserver.disconnect();
    aboutObserver.desconnect();
    ...code for other sections
  };
}, []);