You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何监听返回按钮点击 仅从商品页返回分类页时恢复滚动位置

React监听返回按钮+滚动恢复修复方案

原有代码优化点

先修正现有滚动监听逻辑的性能问题:原代码将scrollPosition加入useEffect依赖,每次滚动都会重新绑定滚动事件,存在不必要的性能消耗,优化后代码如下:

const [scrollPosition, setScrollPosition] = React.useState(0);

React.useEffect(() => {
  const pathName = document.location.pathname.substr(1);
  const handleScroll = () => {
    const currentScrollY = window.scrollY;
    setScrollPosition(currentScrollY);
    if(currentScrollY !== 0){
      sessionStorage.setItem("scrollPosition_"+pathName, currentScrollY);
    }
  };
  window.addEventListener('scroll', handleScroll);
  // 组件卸载时移除监听,避免内存泄漏
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

核心需求实现方案

方案1:通过React Router判断上一个路由(推荐,准确率最高)

第一步:全局存储上一路由路径

在项目根组件App.js中全局维护前后路由的状态,方便所有页面调用:

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

let prevPath = '';
let currentPath = '';

function App() {
  const location = useLocation();
  useEffect(() => {
    prevPath = currentPath;
    currentPath = location.pathname;
  }, [location]);

  // 原有App组件其他逻辑
}

export { prevPath };

第二步:分类页新增上一路由判断逻辑

修改分类页的滚动恢复逻辑,仅当从上一级是商品页时才触发滚动恢复,恢复完成后清空存储的滚动值,避免其他场景复用:

import { prevPath } from './App';

React.useEffect(() => {
  const pathName = document.location.pathname.substr(1);
  const savedScroll = sessionStorage.getItem("scrollPosition_"+pathName);
  // 替换为你项目实际的商品页路由正则规则,示例为匹配/goods/数字 格式的商品页路径
  const isFromGoodsPage = /^\/goods\/\d+$/.test(prevPath);
  
  if (savedScroll && isFromGoodsPage) {
    // 原生方法实现滚动,无需依赖jQuery
    window.scrollTo(0, Number(savedScroll));
    // 恢复完成后删除存储值,避免其他场景触发
    sessionStorage.removeItem("scrollPosition_"+pathName);
  }
}, []);

方案2:直接监听返回按钮触发的popstate事件

如果不需要严格限制来源页,仅需要点击返回按钮时才触发滚动恢复,可以直接监听popstate事件,该事件仅在用户点击浏览器前进/后退按钮、调用history.back()等历史操作时触发,普通路由跳转不会触发:

React.useEffect(() => {
  const pathName = document.location.pathname.substr(1);
  const handleBack = () => {
    const savedScroll = sessionStorage.getItem("scrollPosition_"+pathName);
    if (savedScroll) {
      window.scrollTo(0, Number(savedScroll));
      sessionStorage.removeItem("scrollPosition_"+pathName);
    }
  };
  window.addEventListener('popstate', handleBack);
  return () => window.removeEventListener('popstate', handleBack);
}, []);

注意:如果项目中有其他调用返回方法的业务场景,该方案会同时触发,建议结合上一路由判断使用更稳妥。

内容的提问来源于stack exchange,提问作者user16468845

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 07:36:03