23

Where do I have to put the window.scrollTo(0,0) call in a react component?

I tried to put it directly into render and also tried componentDidUpdate (to wait till everything is rendered), but somehow the scrollbars always stay at the same position.

-- Edit --

The problem was CSS height/overflow of the window and body.

See: https://stackoverflow.com/a/18573599/1016383

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
K..
  • 4,044
  • 6
  • 40
  • 85

8 Answers8

26

window.scrollTo only works when the scroll behavior is set on html.
If scroll is set on body then document.querySelector("body").scrollTo(0,0)

If you have set overflow: scroll on some container inside of the DOM, then that need to be accessed. Assign an id to that. For example I have below div container for which I have set overflow: scroll.

<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="root">
      <div id="scroller">
        <!-- other content -->
      </div>
    </div>    
  </body>
</html>

Then for scrolling behavior, you need to query the scroller.

const scrollToTop = () => {
  document.getElementById("scroller").scroll(0,0)
}

<button onClick={scrollToTop}>Scroll to Top</button>

This would work perfectly.

The Coder
  • 3,447
  • 7
  • 46
  • 81
13

Well, window.scrollTo(0,0) would always stick to the top of the page.

You are correct in saying this code should live in the componentDidMount function, but you need to tell it where to scroll. I would locate the id of the element you want to scroll to and obtain it's y coordinates, than you enter that into the window.scrollTo and it should work. You may need to get the height of the component and add that to this dymamic value you obtained.

Chris Hawkes
  • 11,923
  • 6
  • 58
  • 68
  • So even if it's a window method and I use `0,0` it won't scroll to the top of the page and I need actual coordinates of an element on the page? – K.. Jun 29 '15 at 18:04
  • 1
    well no actually, wherever that is called it should scroll to the top of the page. So are you sure this is being called? have you tried an alert on your componentDidMount function? I thought you were trying to scroll to where your component was located. – Chris Hawkes Jun 29 '15 at 18:25
  • it gets called, it just doesn't do anything. – K.. Jun 29 '15 at 18:35
  • 2
    @ChrisHawkes why must it live in `componentDidMount`, what if you wanted only to scroll after a function has been called? – The Walrus Mar 15 '18 at 16:23
  • @TheWalrus I think K. means if you want to scroll once after the componentDidMount, but if you want to scroll after a specific event effectively I do think it is better to include it in the relevant place of your code's flow – Webwoman Nov 15 '19 at 19:29
9

Another scenario could be that the application is not set up to have the window handle its scrolling. It could be a 'widget' where the window is static and an inner element handles the scrolling. A good way to test this is to enter window.scrollTo(0,0) right there in your console. If your window doesn't pop to the top there, you'll need to seek another solution. Likely you'll need to get the element that is doing the actual scrolling and handle it with Element.scrollTo(0,0)

Reed Black
  • 111
  • 1
  • 6
  • 1
    I think I have the issue you mentioned. I'm working on an open-source project and `window.scrollTo()` does not work in that app. I had to use `document.querySelector('body').scrollTo(0,0)` to make it work. This is weird. – Muchdecal May 25 '20 at 22:58
8

Like @Reed Black mentioned in his answer, the problem might be window.scrollTo(0,0) does not work for the particular app.

I encountered this problem in an open-source project. The app won't scroll using window.scrollTo(0,0) like other websites would.

I had to use document.querySelector('body').scrollTo(0,0) to make it work.

Muchdecal
  • 177
  • 4
  • 8
8

I tried everything I found on this issue with React, the only one that worked for me was with 'scrollIntoView' seen in this below code;

document.getElementById('element')?.scrollIntoView({ behavior: 'smooth' });
Ike Anya
  • 163
  • 1
  • 7
0

Somehow the querySelector didn't work for me. But the getElementById did. Here's an example for trigger the 'scroll back to top' from another component.

export default function View() {
  return <div id='view'> A </div>
}

export default function Button() {
  const backToTop = () => {
    document.getElementById('view').scrollTo({ top: 0, behavior: 
      'smooth' 
    })
  }

  return <button onClick={backToTop}>Back to Top</button>
}

export default function App() {
  return (
    <ComponentA/>
    <Button/>
  )
}
Shin ShiBa
  • 21
  • 3
0

Well, it is React and direct DOM manipulations are unwelcome. One can solve this with ref, however it may seem a little bit cumbersome. Namely, one must have an element like Header on the page visible top and agree that scrolling to have this element in view is what one wants.

The simplified example from my page(with TS) is as follows:

const Page = () => {
  const ref: React.Ref<HTMLHeadElement> = React.createRef();
  const goToHeader = () => {
    if (ref.current) {
      ref.current.scrollIntoView({ behavior: "smooth" });
    }
  };
  return (
    <>
      <Header ref={ref} />
      ...any content here... 
      <button onClick={goToHeader}>TEST</button>
    </>
  );
};

Header is:

const Header = forwardRef((props: Props, ref: Ref<HTMLHeadElement>): JSX.Element | null => {
  return (
    <header className="WeatherInformationsPage__header" id="header" ref={ref}>
      ... any actual content goes here ...
    </header>
  );
});

export default Header;


0

For React, this works perfectly

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