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>
)
In React, relative URLs should always be handled by the link tag provided by the React Router, and pure anchor tags should only be used for absolute paths. You can also think of relative URLs as in-app navigation, for example navigating to a particular route of the app and absolute paths as external links.
This feature has been deprecated because the new structure of Routes is that they should act like components, so you should take advantage of component lifecycle methods instead.
With the react-router v5, we can create routes by wrapping with a component, so that we can easily pass props to the desired component like this.
The component allows you to do more than the normal link element. For instance, because it's a React component you have the benefits of having a state and what not (if you want that). You can see more documentation on here.
React Router Hash Link worked for me and is easy to install and implement:
$ npm install --save react-router-hash-link
In your component.js import it as Link:
import { HashLink as Link } from 'react-router-hash-link';
And instead of using an anchor <a>
, use <Link>
:
<Link to="home-page#section-three">Section three</Link>
Note: I used HashRouter
instead of Router
:
Here is one solution I have found (October 2016). It is is cross-browser compatible (tested in Internet Explorer, Firefox, Chrome, mobile Safari, and Safari).
You can provide an onUpdate
property to your Router. This is called any time a route updates. This solution uses the onUpdate property to check if there is a DOM element that matches the hash, and then scrolls to it after the route transition is complete.
You must be using browserHistory and not hashHistory.
The answer is by "Rafrax" in Hash links #394.
Add this code to the place where you define <Router>
:
import React from 'react'; import { render } from 'react-dom'; import { Router, Route, browserHistory } from 'react-router'; const routes = ( // your routes ); function hashLinkScroll() { const { hash } = window.location; if (hash !== '') { // Push onto callback queue so it runs after the DOM is updated, // this is required when navigating from a different page so that // the element is rendered on the page before trying to getElementById. setTimeout(() => { const id = hash.replace('#', ''); const element = document.getElementById(id); if (element) element.scrollIntoView(); }, 0); } } render( <Router history={browserHistory} routes={routes} onUpdate={hashLinkScroll} />, document.getElementById('root') )
If you are feeling lazy and don't want to copy that code, you can use Anchorate which just defines that function for you. https://github.com/adjohnson916/anchorate
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With