fmsthird
fmsthird

Reputation: 1875

React-router v6 window.scrollTo does not work

I am trying to fix the scrolling issue in React wherein when I was to scroll down to a certain point on the page, and then navigates to another page, that page will begin at the same scroll point as the previous page.

Here's what I tried:

import { useLocation } from 'react-router'

const ScrollToTop: React.FC = () => {
  const { pathname } = useLocation()
  React.useEffect(() => {
    console.log('im scrolling')
    window.scrollTo(0, 0)
  }, [pathname])

  return null
}

export default ScrollToTop

And then imports it like this:

import React from 'react'
import ReactDOM from 'react-dom'

import { BrowserRouter } from 'react-router-dom'

import ScrollToTop from './components/base/ScrollToTop'
import Apps from './App'

ReactDOM.render(
  <BrowserRouter>
    <ScrollToTop />
    <Apps />
  </BrowserRouter>,
  document.getElementById('root'),
)

Im scrolling is printing in the console but the window.scrollTo is not working.
I also tried the useLayoutEffect, but the same result still not scrolling.

Upvotes: 7

Views: 8695

Answers (4)

Mark
Mark

Reputation: 1099

I ended up with this hacky solution that works with react-router-dom v6:

ScrollToTopOnMout.tsx

import { FC, ReactNode, useLayoutEffect } from 'react';
import { useLocation } from 'react-router-dom';

const ScrollToTop: FC<{ children: ReactNode }> = ({ children }) => {
  const { pathname } = useLocation();

  useLayoutEffect(() => {
    window.scrollTo(0, 0);
    document.getElementById('full-content')?.scrollTo(0, 0);
  }, [pathname]);

  return <>{children}</>;
};

export default ScrollToTop;

index.tsx

<BrowserRouter>
  <ScrollToTop>
   <App />
  </ScrollToTop>
</BrowserRouter>

App.tsx

<div id="full-content">
  .....
  .....
  <Routes>
     .....
     .....
     .....
  </Routes>
</div>

Upvotes: 1

fmsthird
fmsthird

Reputation: 1875

For those asking how I targeted the parent container. Here's what worked for me. (probably not a clean one but it works)

import React from 'react'
import { useLocation } from 'react-router'

const ScrollToTop: React.FC = () => {
  const { pathname } = useLocation()

  React.useEffect(() => {
    const el = document.getElementById('container-main') // id of the parent
    el.scrollTo(0, 0)
  }, [pathname])

  return null
}

export default ScrollToTop

And use it like this

<div id="container-main">
  <ScrollToTop />
  ....
</div>

Upvotes: 0

Josh
Josh

Reputation: 949

I had this same issue with react-router v6 and using the following instead of window.scrollTo(0, 0) worked for me:

useEffect(() => {
    document.body.scrollTo(0, 0); 
});

Upvotes: 3

calvinf
calvinf

Reputation: 3914

Try grabbing document.documentElement or another specific element instead of window.

const location = useLocation();
useLayoutEffect(() => {
  document.documentElement.scrollTo(0, 0);
}, [location.pathname]);

Related: react-router scroll to top on every transition

Upvotes: 4

Related Questions