React smooth scroll to top of page when route changes

React smooth scroll to top of page when route changes

React Router Dom is a great and the most popular React navigation and routing library. However, it doesn't come bundled scroll management. If you navigate to a new route you have to handle scroll restoration manually(on your own). So much work! There are some libraries that help with this but the idea is to keep the number of libraries you use in your app as minimal as possible. So what's the solution?

If you have a long content page and then go to another long content page, you will stay scrolled down by default. This is not good user experience and honestly shocking coz who likes reading text from the bottom up. To come up with this simple solution, we'll use the useEffect and useLocation hooks. I'm assuming you already know the react basics and can comfortably use hooks and components.

This is the component we are going to create to achieve the scroll-to-top feature on route changes:

import { useEffect } from "react"
import { useLocation } from "react-router-dom"

const ScrollToTop = () => {
    const{ pathname} = useLocation()
   //the use effect ensures the function runs when the route changes
    useEffect(() => {
       // the inbuilt browser function window.scrollTo helps scroll the page 
       // to the top when given the parameter top as 0.
       // behaviour smooth makes the scroll smooth and not snappy
        window.scrollTo({ top: 0, behavior: 'smooth' })  
    }, [pathname])

    return null
}

export default ScrollToTop

We then need to ensure that this component takes effect for the whole app. We can do this by placing this component right below the opening tag. Alernatively, you can have the ScrollToTop component accept other components as children and thus wrap all the Routes compnents within it.

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

import LandingPage from "./HomePage"
import ProductPage from "./AboutPage"
import ScrollToTop from "./ScrollToTop"

const App = () => {
  return (
    <Router>
     // place components just below the Router component but above the Routes 
     // component
      <ScrollToTop/>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/product" element={<AboutPage />} />
        </Routes>
    </Router>
  )
}

export default App

This will ensure the page scrolls to the top smoothly every time the route changes. Happy coding!