skip to Main Content

I am using ReactJs with React-Router-DOM. I have a navbar with links such as "home," "about," "services," "portfolio," and "contact."

The "home" and "about" links are single-page scroll links, while "services," "portfolio," and "contact" are on different pages. I am using an anchor tag <a> instead of the Link tag from "react-router-dom" because the Link tag doesn’t behave as expected for single-page scroll links.

Now, when I navigate from the "home" link to the "about" link, it changes the current URL from domain to domain/#about. Then, if I go from domain/#about to the "services" page, the current URL changes from domain/#about to domain/services.


Here’s where my problem begins:

if I am on any "services," "portfolio," or "contact" page and try to go back to the home and about pages, for example, when the current URL is domain/services and I click on the "about" link, the current URL changes from domain/services to domain/services#about. It doesn’t go back to domain/#about; instead, it changes to domain/services#about.

This is what I am doing on my Navbar component

import React, { useEffect } from "react";
import { Link, useLocation } from "react-router-dom";
import "./css/navbar.css";
import Logo from "./Logo";

function Navbar(props) {
  const location = useLocation();

  useEffect(() => {
    console.log(location);
  }, [location]);

  const singlePageScrollLinks = () => {
    return (
      <>
        <li className="nav-item">
          <a
            href="#home"
            className={`nav-link ${
              location.pathname === "/" && location.hash === "#home"
                ? "active"
                : ""
            }`}
          >
            Home
          </a>
        </li>
        <li className="nav-item">
          <a
            href="#about"
            className={`nav-link ${
              location.pathname === "/" && location.hash === "#about"
                ? "active"
                : ""
            }`}
          >
            About
          </a>
        </li>
      </>
    );
  };

  return (
    <div
      style={{
        position: "sticky",
        top: "-2px",
        backgroundColor: "#2c2c2c",
        zIndex: "2",
      }}
      id="nav-page"
    >
      <div className="d-flex justify-content-between list-unstyled top-nav">
        <li>+91 9876543210</li>
        <li>[email protected]</li>
      </div>
      <nav
        className="navbar navbar-expand-lg bg-body-tertiary custom-nav"
        style={{ borderRadius: "45px 0 0 0" }}
      >
        <div className="container-fluid">
          <Link className="navbar-brand" to="/" style={{ width: "1px" }}>
            <Logo />
          </Link>
          <button
            className="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span className="navbar-toggler-icon"></span>
          </button>
          <div className="collapse navbar-collapse" id="navbarSupportedContent">
            <ul className="navbar-nav ms-auto mb-2 mb-lg-0">
              {singlePageScrollLinks()}
              <li className="nav-item">
                <Link className="nav-link" to="/services">
                  Services
                </Link>
              </li>
              <li className="nav-item">
                <Link className="nav-link" to="/portfolio">
                  Portfolio
                </Link>
              </li>
              <li className="nav-item">
                <Link className="nav-link" to="/contact">
                  Contact
                </Link>
              </li>
            </ul>
          </div>
        </div>
      </nav>
    </div>
  );
}

export default Navbar;

2

Answers


  1. Th problem in your navigation is you are just appending a hash. Your navbar code should be

    import React, { useEffect } from "react";
    import { Link, useLocation } from "react-router-dom";
    import "./css/navbar.css";
    import Logo from "./Logo";
    
    function Navbar(props) {
      const location = useLocation();
    
      useEffect(() => {
        console.log(location);
      }, [location]);
    
      const singlePageScrollLinks = () => {
        return (
          <>
            <li className="nav-item">
              <a
                href="/#home"
                className={`nav-link ${
                  location.pathname === "/" && location.hash === "#home"
                    ? "active"
                    : ""
                }`}
              >
                Home
              </a>
            </li>
            <li className="nav-item">
              <a
                href="/#about"
                className={`nav-link ${
                  location.pathname === "/" && location.hash === "#about"
                    ? "active"
                    : ""
                }`}
              >
                About
              </a>
            </li>
          </>
        );
      };
    
      return (
        <div
          style={{
            position: "sticky",
            top: "-2px",
            backgroundColor: "#2c2c2c",
            zIndex: "2",
          }}
          id="nav-page"
        >
          <div className="d-flex justify-content-between list-unstyled top-nav">
            <li>+91 9876543210</li>
            <li>[email protected]</li>
          </div>
          <nav
            className="navbar navbar-expand-lg bg-body-tertiary custom-nav"
            style={{ borderRadius: "45px 0 0 0" }}
          >
            <div className="container-fluid">
              <Link className="navbar-brand" to="/" style={{ width: "1px" }}>
                <Logo />
              </Link>
              <button
                className="navbar-toggler"
                type="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent"
                aria-expanded="false"
                aria-label="Toggle navigation"
              >
                <span className="navbar-toggler-icon"></span>
              </button>
              <div className="collapse navbar-collapse" id="navbarSupportedContent">
                <ul className="navbar-nav ms-auto mb-2 mb-lg-0">
                  {singlePageScrollLinks()}
                  <li className="nav-item">
                    <Link className="nav-link" to="/services">
                      Services
                    </Link>
                  </li>
                  <li className="nav-item">
                    <Link className="nav-link" to="/portfolio">
                      Portfolio
                    </Link>
                  </li>
                  <li className="nav-item">
                    <Link className="nav-link" to="/contact">
                      Contact
                    </Link>
                  </li>
                </ul>
              </div>
            </div>
          </nav>
        </div>
      );
    }
    
    export default Navbar;
    
    

    For scrolling you can use scrollIntoView but in a react way for better performance like this on your home page:

    export default function Home() {
      const location = useLocation();
      const homeRef = useRef();
    
      useEffect(() => {
        if (location.hash) {
          scrollToEle(location.hash);
        }
      }, [location]);
    
      const scrollToEle = (id) => {
        const ele = homeRef.current.querySelector(`${id}`);
        if (ele) {
          ele.scrollIntoView({ behaviour: 'smooth' });
        }
      };
      return (
        <div ref={homeRef}>
          <div id="contact">Contact</div>
        </div>
      );
    }
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search