admin管理员组

文章数量:1122832

I’m working on a React app using react-router-dom. I want the page to scroll to the top every time the route changes. Here’s what I’ve tried:

Used a custom hook with useEffect:

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

const useScrollToTop = () => {
  const { pathname } = useLocation();

  useEffect(() => {
    console.log("Attempting to scroll to top"); // Logs correctly
    window.scrollTo({
      top: 0,
      behavior: "auto",
    });
    console.log("Scroll executed"); // Also logs correctly
  }, [pathname]);
};

export default useScrollToTop;

Added the hook in my App.tsx:

import useScrollToTop from './hooks/useScrollToTop';

const App = () => {
  useScrollToTop();
  return (
    <BrowserRouter>
      <Routes>
        {/* My routes */}
      </Routes>
    </BrowserRouter>
  );
};

Verified that window.scrollTo executes (logs appear), but the page doesn’t scroll to the top.

I also tested with:

a. useLayoutEffect instead of useEffect.
b. Forcing a delay using setTimeout.
c. Checking for scrollable elements (html, body, or a custom container).
d. CSS fixes like ensuring html, body { height: auto; overflow: visible; }.
e. Despite all this, the page still doesn’t scroll to the top. Is there anything I’m missing or any interference I should check for?

I’m working on a React app using react-router-dom. I want the page to scroll to the top every time the route changes. Here’s what I’ve tried:

Used a custom hook with useEffect:

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

const useScrollToTop = () => {
  const { pathname } = useLocation();

  useEffect(() => {
    console.log("Attempting to scroll to top"); // Logs correctly
    window.scrollTo({
      top: 0,
      behavior: "auto",
    });
    console.log("Scroll executed"); // Also logs correctly
  }, [pathname]);
};

export default useScrollToTop;

Added the hook in my App.tsx:

import useScrollToTop from './hooks/useScrollToTop';

const App = () => {
  useScrollToTop();
  return (
    <BrowserRouter>
      <Routes>
        {/* My routes */}
      </Routes>
    </BrowserRouter>
  );
};

Verified that window.scrollTo executes (logs appear), but the page doesn’t scroll to the top.

I also tested with:

a. useLayoutEffect instead of useEffect.
b. Forcing a delay using setTimeout.
c. Checking for scrollable elements (html, body, or a custom container).
d. CSS fixes like ensuring html, body { height: auto; overflow: visible; }.
e. Despite all this, the page still doesn’t scroll to the top. Is there anything I’m missing or any interference I should check for?

Share Improve this question edited Nov 22, 2024 at 16:21 flash asked Nov 22, 2024 at 16:02 flashflash 1,51112 gold badges72 silver badges160 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Issue

Your custom hook is clearly being called outside the router:

const App = () => {
  useScrollToTop(); // <-- needs routing context
  return (
    <BrowserRouter> // <-- provides routing context
      <Routes>
        {/* My routes */}
      </Routes>
    </BrowserRouter>
  );
};

So it can't possibly have access to the routing context that BrowserRouter provides to the useLocation hook and all other RRD hooks and components called/rendered within its sub-ReactTree, e.g. its children.

In fact, there should be a console error about that useLocation hook call:

Solution Suggestion

Move the useScrollToTop hook to a component rendered within the router so that it can properly access the routing context.

Below I have just converted the hook into a React component so that it is renderable as JSX within the router and able to call side-effects.

Example:

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

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

  useEffect(() => {
    window.scrollTo({
      top: 0,
      behavior: "auto",
    });
  }, [pathname]);

  return null;
};

export default ScrollToTop;
const App = () => {
  return (
    <BrowserRouter>   // <-- provides routing context
      <ScrollToTop /> // <-- can access routing context
      <Routes>
        {/* My routes */}
      </Routes>
    </BrowserRouter>
  );
};

本文标签: reactjsReact windowscrollTo not working on route changeStack Overflow