0

I have a React app and I had to use Scroll To Top. I have used this before many times, and never had problems as explained:

https://reactrouter.com/web/guides/scroll-restoration/scroll-to-top

The funny thing is I can't get it working now for some reason. I tried many ways, I changed the structure of my Router, and still doesn't work.

What really happens is I get the last window position of the component before the Route change, and I obviously want to position to top on each Route change

This is my ScrollToTop.js

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

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}

This is inside my App.js

 <Router  basename={'/'}> 
  <NavMobile />
  <Cart />

    <ScrollToTop />

     <Switch>
            <Route exact path="/home" component={Home} />
            <Route exact path="/book" component={Book} />
     </Switch>
</Router>    
Dam Jankov
  • 11
  • 2

3 Answers3

1

You can use the "scrollIntoView" web API, on the "root" element, adding this on App.js.

useEffect(()=> {
    document.getElementById('root').scrollIntoView();
}, [window.location.pathname])

Also, depending on the use case, you can pass props as: {behavior:'smooth'}, for a nice scroll effect.

useEffect(()=> {
    document.getElementById('root').scrollIntoView({behavior: 'smooth' });  
}, [window.location.pathname])
Lorin Muller
  • 11
  • 1
  • 1
  • Did you added also the “window.location.pathname” as dependency on useEffect? – Lorin Muller Sep 01 '21 at 18:18
  • Yes I did add it. – Dam Jankov Sep 01 '21 at 18:20
  • I even tried: document.getElementById('root').scrollIntoView({behavior: 'smooth', block: 'end'}); I tried this so I know if this is fired at all, and it comes out that on refresh it is fired and the page scroll starts at the bottom. However on route changes it still has the same behaviour as before with keeping the scroll position from the previous component. – Dam Jankov Sep 01 '21 at 18:26
  • It is a dynamic route, like /post/:id, and you're going from "/post/1" to "/post/2" ? – Lorin Muller Sep 02 '21 at 08:20
  • No they are not dynamic routes. So I am going from /home to /other etc. See my index.js if that has to do anything with this: ReactDOM.render( , document.getElementById("root") ); – Dam Jankov Sep 02 '21 at 11:07
  • I fixed it, thanks anyways. https://stackoverflow.com/questions/55336831/how-to-fix-gatsby-js-link-component-retaining-scroll-position-and-not-resetting this helped me. The issue was overflow-x: hidden on the body element. – Dam Jankov Sep 02 '21 at 11:32
  • Awesome, I'm happy that you solved the issue ;) – Lorin Muller Sep 02 '21 at 11:39
  • I am not sure what is really happening behind the scenes to cause this issue. I posted this if anyone else is curious too. https://stackoverflow.com/questions/69029650/why-react-router-scroll-restoration-window-scrollto0-0-as-explained-on-r – Dam Jankov Sep 02 '21 at 11:46
0

You can also just put it wherever you need it

useEffect(() => {
    window.scrollTo(0, 0);
  }, []);
  • I have just put it in components where I needed to scroll on top when I switch between pages – Alekbarova Aizhan Sep 01 '21 at 17:56
  • useEffect is fired on initial component render, the route changes don't fire useEffect as far as I know – Dam Jankov Sep 01 '21 at 18:04
  • My issue is the scroll keeps the position on the route changes. So let's say if I have the page scrolled until somewhere middle, and change to another route, the other component will also show with the initial scroll position somewhere on the middle. – Dam Jankov Sep 01 '21 at 18:10
0

The issue was caused by overflow-x: hidden on the body element.

This helped me:

How to fix Gatsby JS Link component retaining scroll position and not resetting to top

Dam Jankov
  • 11
  • 2