Use anchors with react-router

How can I use react-router, and have a link navigate to a particular place on a particular page? (e.g. /home-page#section-three)

Details:

I am using react-router in my React app.

I have a site-wide navbar that needs to link to a particular parts of a page, like /home-page#section-three.

So even if you are on say /blog, clicking this link will still load the home page, with section-three scrolled into view. This is exactly how a standard <a href="/home-page#section-three> would work.

Note: The creators of react-router have not given an explicit answer. They say it is in progress, and in the mean time use other people's answers. I'll do my best to keep this question updated with progress & possible solutions until a dominant one emerges.

Research:


How to use normal anchor links with react-router

This question is from 2015 (so 10 years ago in react time). The most upvoted answer says to use HistoryLocation instead of HashLocation. Basically that means store the location in the window history, instead of in the hash fragment.

Bad news is... even using HistoryLocation (what most tutorials and docs say to do in 2016), anchor tags still don't work.


https://github.com/ReactTraining/react-router/issues/394

A thread on ReactTraining about how use anchor links with react-router. This is no confirmed answer. Be careful since most proposed answers are out of date (e.g. using the "hash" prop in <Link>)


Answers:

Answer

This solution works with react-router v5

import React, { useEffect } from 'react'
import { Route, Switch, useLocation } from 'react-router-dom'

export default function App() {
  const { pathname, hash } = useLocation()

  useEffect(() => {
      // if not a hash link scroll to top
      if(hash===''){
          window.scrollTo(0, 0)
      }
      // else scroll to id
      else{
          setTimeout(
              () => {
                  const id = hash.replace('#', '');
                  const element = document.getElementById(id);
                  if (element) {
                      element.scrollIntoView();
                  }
              },
              0
          );
      }
  }, [pathname]) // do this on route change

  return (
      <Switch>
        <Route exact path="/" component={Home} />
        .
        .
      </Switch>
  )
}

In the component

<Link to="/#home"> Home </Link>

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.