Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>)


like image 370
Don P Avatar asked Oct 27 '16 08:10

Don P


People also ask

Can we use anchor tag in React?

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.

Is React Router deprecated?

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.

Can you pass props through React Router?

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.

Why should you use React Router's link component instead of a basic a tag in React?

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.


2 Answers

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:

like image 184
maledr53 Avatar answered Oct 16 '22 10:10

maledr53


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

like image 31
Don P Avatar answered Oct 16 '22 10:10

Don P