Hash Link Routing for React Applications

When working on a client web application earlier this year I needed to support a common navigation implementation. The users would need to be able to navigate directly to an element on a page using hash link routing.

My team and I were leveraging react router to handle our page navigation. After doing some research I reached for the most popular npm package I could find, react-router-hash-link.

This package surfaces some components to be used as an alternative to react-router-dom components such as Link and NavLink. The replacement components allow the user to navigate directly to elements on the page if the path specified in the value of the to property includes a hash fragment and the target element has in id identical to the hash fragment value. There is a stipulation that you must be using react router's BrowserRouter to take advantage of this package which was fine with us because that's exactly what we were using.

However, for our use case, I quickly found that the flagship scroll-to-element functionality wasn't working as needed in the following circumstances:

  • Browser forward/back operation to a URL with a hash fragment
  • Opening a URL with a hash fragment in a new tab
  • Page refresh

To my surprise this seemingly common problem was disappointingly not fully solved. Don't get me wrong, react-router-hash-link is a completely valid solution for many use cases. Unfortunately, there were too many unsupported features for our use case.

At this point I had taken a look at a few popular packages in hopes that one would "just work". However, I ended up having to hand-roll the solution to fit our customer's needs. Using inspiration from react-router-hash-link and this blog post I created react-hash-link.

react-hash-link works in all of the following situations from the README.

  • Navigating to a URL with a hash fragment and corresponding element on the page
  • Opening qualifying URLs/pages in a new browser tab or window
  • Forward browser navigation
  • Backward browser navigation
  • Page reload
  • Works with react-router but not dependent on it
  • Works with server-side rendering
  • All of the above scenarios function correctly when used across all major browsers (including IE)

Check out the differences between these packages by comparing a sample app using react-router-hash-link and the same app using react-hash-link.