12

I've been struggling with that issue for 2 hours or so and can't find a way to do it.

I would like to update my url hash (#home, #about etc..) when i'm scrolling through those sections and by the same way highlight the current section in my navbar. I've found different answers in Jquery but the thing is that i'm using ReactJS and i've been told that it is not a good idea / useful to use Jquery with ReactJS.

I've also found and tried this package : https://www.npmjs.com/package/react-scrollable-anchor But the problem is the hash update only when the scrolling is over.

Edit :

<ul>
  <li>
      <a href="#">Home</Link>
  </li>
  <li>
      <a href="#about">About</Link>
  </li>
  <li>
      <a href="#skills">Skills</Link>
  </li>
</ul>

When i'm clicking on About my url then goes as : localhost:3000/#about and automatically scroll to this section, everything is fine from here. But if I scroll(without clicking anywhere) to the Skills section then i want the url to automatically go to localhost:3000/#skills and the navbar hightlight the Skills.

Hope you can help me through this issue. Thanks !

Kaaedan
  • 121
  • 4

2 Answers2

0

you can solve this by checking section height and scrolling position window.history.replaceState(null, null, #${section.id}); .here i attached event listener for checking scrolling position

import React, { useEffect } from "react";

function Test() {
  useEffect(() => {
    const handleScroll = () => {
        const sections = document.querySelectorAll('section[id]');
        const scrollPosition = window.pageYOffset;
  
        sections.forEach(section => {
          const sectionTop = section.offsetTop;
          console.log(sectionTop , section.offsetHeight , "" , section , scrollPosition) ;
          const sectionBottom = sectionTop + section.offsetHeight;
  
          if (scrollPosition >= sectionTop  && scrollPosition < sectionBottom) {
            window.history.replaceState(null, null, `#${section.id}`);
          }
        });
      };

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);

  return (
    <div>
      <ul>
        <li>
          <a href="#">Home</a>
        </li>
        <li>
          <a href="#about">About</a>
        </li>
        <li>
          <a href="#skills">Skills</a>
        </li>
      </ul>

      <section id="about">
        <h2>About</h2>
        <p>you can put here  content to test</p>
      </section>

      <section id="skills">
        <h2>Skills</h2>
        <p>you can put here  content to test</p>
      </section>
    </div>
  );
}

export default Test;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
jainam shah
  • 101
  • 1
  • 5
-2

You should simply use 'react-router-dom' library for routing and handling Url paths. they has very clear documentation https://reactrouter.com/web/example/basic. For You help Simply define the path in the to prop of Link where you want to go !

       <ul>
          <li>
            <Link to="/test">Home</Link>
          </li>      
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        </ul>

Now simply navigate to that declared path by wrapping it in the

          <Route exact path="/test">
            <Home />
          </Route>

By doing all this.Url Hash will not been a problem any more ;)

Muzamil ijaz
  • 163
  • 10
  • 8
    I'am not sure that you fully understand my problem, I'm talking about section on a single page, I don't want to navigate through few pages. I tried as you said and changing with section but the thing is that, it just render the component in the pathname. I'm editing my post to be more clear :) – Kaaedan Sep 02 '20 at 22:35