DEV Community

loading...

Reach Router scroll top fix - my 2nd npm package!

darksmile92 profile image Robin Kretzschmar ・2 min read

I did a lot of projects with NextJS and recently had to do one with create-react-app again.
So I quickly remembered how tedious it was to fiddle around with React-Router and searched for an alternative.

Reach Router seemed like a good alternative. I quickly noticed one problem:

The problem to solve

When using Reach Router, the accessibility features are turned on by default.
The official docs say:

Focus Management
Whenever the content of a page changes in response to a user interaction, the focus should be moved to that content; otherwise, users on assistive devices have to search around the page to find what changed–yuck! Without the help of a router, managing focus on route transitions requires a lot effort and knowledge on your part.

Reach Router provides out-of-the-box focus management so your apps are significantly more accessible without you breaking a sweat.

When the location changes, the top-most part of your application that changed is identified and focus is moved to it.

In my case, after scrolling to the bottom at one page and navigating to another page, the newly loaded page will be scrolled to the same distance as the previous, if the content is longer than the viewport height.
This can be disabled by setting primary={false} at the Router component of Reach, but this would also disable the accessibility features.

The solution

I got inspired by a couple of Stackoverflow answers but none of them were using React hooks and none could be implemented quickly enough for me.
So I took the time and wrote a solution using hooks.
It consisted of 2 parts:

// new component OnRouteChangeWorker.js
import React, { useEffect, useRef } from "react";

const OnRouteChangeWorker = props => {
    const locationRef = useRef("");
    useEffect(() => {
        if (props.location.pathname !== locationRef.current) {
            locationRef.current = props.location.pathname;
            props.action();
        }
    });

    return null;
};

export default OnRouteChangeWorker;
Enter fullscreen mode Exit fullscreen mode
// in App.js - global entry file
import { Location, Router } from "@reach/router";
import OnRouteChangeWorker from "./components/OnRouteChangeWorker";

// ...
function App() {
  return (
    <div>
        <Router>
          <HomePage path="/" />
          <ImpressumPage path="terms" />
          <PrivacyPage path="privacy" />
        </Router>
        <OnRouteChange
          action={() => {
            window.scrollTo(0, 0);
          }}
        />
      </div>
  );
// ...
Enter fullscreen mode Exit fullscreen mode

reach-router-scroll-top

Want to have the accessibility features of Reach Router and scroll to top after navigating? Get it working with just this one component!

Install

npm install --save reach-router-scroll-top
Enter fullscreen mode Exit fullscreen mode

Quickstart

// in your App.js / entry point
import { OnRouteChange } from "reach-router-scroll-top";
// ...
function App() {
    return (
        <div>
            <Router>
                <HomePage path="/" />
            </Router>
            {/* add it after the router! */}
            <OnRouteChange />
        </div>
    );
}
// ...
Enter fullscreen mode Exit fullscreen mode

What it solves

When using Reach Router, the accessibility features are turned on by default. After scrolling to the bottom at one page and navigating to another page, the newly loaded page will be scrolled to the same distance as the previous This can be disabled by setting primary={false} at the Router component of Reach, but this…

Why a npm package?

I wanted to archive the following:

  • do something in Typescript
  • learn how to publish a npm package myself
  • provide this solution for others to quickly integrate into their projects

Discussion (0)

pic
Editor guide