Why react new page render from the bottom of the screen?

Viewed 3956

I have multiple pages in my react project and, whenever I switch from one page to another the page position starts from the bottom but, I want to stay on top after rendering the page. I'm currently using router v5 and, I can't find any solution for router v5.

I've also tried another version solution but, It didn't work and could you please help me to solve this problem.

These are some of the examples I've tried so far but, not single ones have worked.

<Router onUpdate={() => window.scrollTo(0, 0)} history={createBrowserHistory()}>
  ...
</Router>
function handleUpdate() {
  let {
    action
  } = this.state.location;

  if (action === 'PUSH') {
    window.scrollTo(0, 0);
  }
}

...

<Router
  onUpdate={handleUpdate}
/>
3 Answers

This is the solution I use to solve this problem. Create a new component:

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

const ScrollToTop = ({ children }) => {
  const { pathname } = useLocation();

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

  return children || null;
};

export default ScrollToTop;

and wrap your app contents in it INSIDE of the browser router

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import ScrollToTop from './components/scroll-to-top/scroll-to-top';

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <ScrollToTop>
          <div />
        </ScrollToTop>
      </BrowserRouter>
    </div>
  );
}

export default App;

Create the next component:

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;
}

Import it in your index.js and use it before Switch component, like this:

  <ScrollToTop />
  <Switch>  
    ...
  </Switch>

And it should work.

The above methods of using window.scrollToView(0, 0) doesn't work for me. Thus, another workaround/solution which works for me is to have a div at the top with a ref. The scrollIntoView method would then be called in the useEffect hook to scroll the div into view on render.

import React, { useEffect, useRef } from "react";

const TestComponent = () => {
const topContainer = useRef();

useEffect(() => {
  // To make sure page starts from the top
  topContainer.current.scrollIntoView({ block: "end", behavior: 'smooth' });
  }, []);

return (
  <>
    <div ref={topContainer} />
    <div>Component to be rendered here</div>
  </>
  );
};

The property behavior: 'smooth' passed to scrollIntoView could be omitted too, if you do not want smooth animation of the scroll.

Related