点击浏览器返回按钮时滚动到页面顶部 (React)

5

每次URL改变时(包括页面重新加载),我需要滚动到页面顶部。

一切都有效,但我在使用浏览器的返回按钮时遇到了问题。即使路径名改变,页面也不会像应该的那样滚动到顶部,在所有其他情况下都正常工作(页面重新加载和常规链接导航)。

我尝试通过创建一个专门用于后退按钮的自定义钩子来解决这个问题,但它的行为不是我所期望的。我还尝试了许多其他方法,但好像没有任何方法能够处理浏览器返回按钮。

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

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

  const useBackButton = () => {
    const [isBack, setIsBack] = useState(false);
    const handleEvent = () => {
      setIsBack(true);
    };
    useEffect(() => {
      window.addEventListener("popstate", handleEvent);
      return () => window.removeEventListener("popstate", handleEvent);
    });
    return isBack;
  };

  const backButton = useBackButton();
  console.log(backButton);

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

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

  return null;
};

export default ScrollToTop;

如果您正在使用单页React应用程序,则不会预期在页面导航时触发onbeforeunload,因为您实际上并没有离开该页面。像这样的东西可能很有用:使用react-router检测路由更改 - DBS
您可以创建一个链接,然后在其中创建一个按钮,并将href = #放入其中。 - Elio Bteich
你是对的,但那只是针对页面重新加载。第一个 useEffect 是为了导航和返回按钮。 - giosan
url的更改通过useLocation中的常量pathname进行跟踪,但是由于某种原因,即使在按下浏览器返回按钮时url发生更改,scrollTo(0, 0)也不会被触发。 - giosan
2个回答

4

我认为在这里没有必要使用beforeunload事件,但还是会包含它。不需要使用"popstate"事件的事件监听器,可以使用useNavigationType钩子来明确检查POP事件类型。

注意:对于beforeunload事件,请使用window.addEventListener,以避免污染窗口对象。

示例:

import { NavigationType, useLocation, useNavigationType } from "react-router-dom";

const useBackButton = () => {
  const navType = useNavigationType();
  return navType === NavigationType.Pop;
};

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

  const isPop = useBackButton();

  const scrollToTop = () => window.scrollTo(0, 0);

  useEffect(() => {
    scrollToTop();
  }, [pathname, isPop]);

  useEffect(() => {
    window.addEventListener("beforeunload", scrollToTop);
    return () => {
      window.removeEventListener("beforeunload", scrollToTop);
    };
  }, []);
};

用法:

function App() {
  useScrollToTop();

  return (
    ...
  );
}

Edit scroll-to-top-on-browser-back-button-click-react


1

以下是使用React hooks的解决方案:

const [showsScrolBtn, setShowScrolBtn] = useState(false);

useEffect(() => {
  const handleButtonVisibility = () => {
    window.pageYOffset > 300 ? setShowScrolBtn(true) : setShowScrolBtn(false);
  };

  window.addEventListener("scroll", handleButtonVisibility);
  return () => {
    window.addEventListener("scroll", handleButtonVisibility);
  };
}, []);

{
  showsScrolBtn && (
    <div
      id="scrolToTop"
      onClick={() => {
        window.scrollTo({
          top: 0,
          left: 0,
          behavior: "smooth",
        });
      }}
      style={{
        position: "fixed",
        bottom: "60px",
        right: "60px",
        color: "gray",
        textAlign: "center",
        cursor: "pointer",
        fontSize: "4em",
        lineHeight: 0,
        textDecoration: "none",
      }}
    >
      Click To Move Top
    </div>
  );
}

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接