Search code examples
javascriptreactjsreact-routerreact-router-dom

Nav Link not rerendering page when clicked. Force update freezes page


I have a nav bar for a website I'm building. The links in the nav bar to a section (#id) in the page but do not go to the section and only update the url. If I type in the url in the address bar, it works correctly but when using the link nothing happens.

It only works if I force the page to rerender, but after rerendering the page freezes and I get an error in the console: Uncaught TypeError: Cannot read properties of undefined (reading 'forceUpdate'). I added an onClick and also tried using setState to force re-render.

Index.js

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

App.js

function App() {
  return (
    <div>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/home" element={<Home />} />
      </Routes>
    </div>
  );
}

export default App;

Home.jsx

function Home() {
  return (
    <div>
      <Container fluid>
        <NavBar />
        <HomeContent />
      </Container>
      <Pricing />
      <Footer />
    </div>
  );
}

export default Home;

NavBar.jsx

function handleClick() {
  this.setState({ state: this.state });
  // this.forceUpdate();
}

function NavBar() {
  return (
    <>
      <Navbar variant="dark" expand="lg">
        <Container>
          <Navbar.Brand onClick={handleClick} as={Link} to="/home">
          </Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="justify-content-end flex-grow-1 pe-3">
              <Nav.Link onClick={handleClick} as={Link} to="/home">
                Home
              </Nav.Link>
              <Nav.Link onClick={handleClick} as={Link} to="/home#pricing">
                Pricing
              </Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    </>
  );
}

export default NavBar;

Pricing.jsx

function Pricing() {
  return (
    <section id="pricing">
      <h2 className="section-heading">This is the pricing section</h2>
    </section>
  );
}

export default Pricing;

I also tried using withRouter on the NavBar component

I read that if I have to resort to forcing the page to render then I may be doing something wrong but I'm new to React and I've been searching for the past couple of days on better ways to do this but still couldn't find a better way to do it.


Solution

  • this.setState and this.forceUpdate are older React class-based-only component methods. They won't work in React function components.

    react-router-dom alone doesn't deal/handle with hash links, i.e. navigating to a specific route path and then scrolling to a specific hash anchor. Currently the react-router-hash-link still works with react-router-dom@6. Import the HashLink from react-router-hash-link and use instead of the Link component from RRD.

    Example:

    import React from "react";
    import { Nav, Navbar } from "react-bootstrap";
    import { Link } from "react-router-dom";
    import { HashLink } from "react-router-hash-link"; // <-- import hash link
    
    function NavBar() {
      return (
        <Navbar bg="dark" variant="dark" expand="lg">
          <Navbar.Brand as={Link} to="/home"></Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="justify-content-end flex-grow-1 pe-3">
              <Nav.Link as={Link} to="/home">
                Home
              </Nav.Link>
              <Nav.Link as={HashLink} to="/home#pricing"> // <-- hash link
                Pricing
              </Nav.Link>
              <Nav.Link as={HashLink} to="/home#about">   // <-- hash link
                About
              </Nav.Link>
              <Nav.Link as={HashLink} to="/home#contact"> // <-- hash link
                Contact
              </Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Navbar>
      );
    }
    
    export default NavBar;
    

    Edit nav-link-not-rerendering-page-when-clicked-force-update-freezes-page