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

React+React Router无限滚动页面返回时恢复滚动位置方案咨询

解决React Router无限滚动页面返回时的滚动位置与数据恢复问题

我之前也碰到过一模一样的场景——无限滚动加载广告,跳转商品页后返回,不仅滚动位置没了,之前加载的50条数据也只剩前10条,Chrome原生的滚动恢复完全不管用。结合React和React Router,给你几个实用的解决方案:

方案一:通过React Router的location.state传递状态

这是最直接的方式,在跳转商品页时,把当前的滚动位置、已加载的广告列表存在路由的state里,返回时读取这些数据恢复状态。

步骤:

  1. 跳转时保存状态:在广告预览的点击事件里,获取当前滚动位置和已加载的广告数据,通过navigate方法传递到目标页面:
import { useNavigate } from 'react-router-dom';

const AdList = () => {
  const navigate = useNavigate();
  const [ads, setAds] = useState([]); // 存储已加载的所有广告

  const handleAdClick = (adId) => {
    // 获取当前滚动位置
    const scrollPosition = window.scrollY;
    // 跳转到商品页并携带状态
    navigate(`/product/${adId}`, {
      state: {
        previousScroll: scrollPosition,
        loadedAds: [...ads]
      }
    });
  };

  // 无限滚动加载逻辑...
};
  1. 返回时恢复状态:在广告列表页面,通过useLocation读取路由state,在组件挂载时恢复数据和滚动位置:
import { useLocation, useEffect } from 'react-router-dom';

const AdList = () => {
  const location = useLocation();
  const [ads, setAds] = useState([]);

  useEffect(() => {
    // 检查是否有来自商品页的返回状态
    if (location.state?.loadedAds) {
      // 恢复已加载的广告数据
      setAds(location.state.loadedAds);
      // 恢复滚动位置(需要等DOM渲染完成)
      setTimeout(() => {
        window.scrollTo(0, location.state.previousScroll);
      }, 0);
    }
  }, [location.state]);

  // 无限滚动加载逻辑...
};

方案二:用sessionStorage持久化状态

如果担心路由state在页面刷新后丢失,可以用sessionStorage来存储滚动位置和已加载数据,这种方式更稳定:

步骤:

  1. 跳转前保存状态到sessionStorage:
const handleAdClick = (adId) => {
  const scrollPosition = window.scrollY;
  // 把数据转成字符串存在sessionStorage
  sessionStorage.setItem('adListState', JSON.stringify({
    scrollPosition,
    loadedAds: [...ads]
  }));
  navigate(`/product/${adId}`);
};
  1. 页面挂载时读取并恢复:
useEffect(() => {
  const savedState = sessionStorage.getItem('adListState');
  if (savedState) {
    const { scrollPosition, loadedAds } = JSON.parse(savedState);
    setAds(loadedAds);
    setTimeout(() => {
      window.scrollTo(0, scrollPosition);
    }, 0);
    // 恢复后可以清除存储,避免下次进入页面自动恢复(可选)
    sessionStorage.removeItem('adListState');
  }
}, []);
  1. 监听页面卸载(可选):如果用户可能直接刷新商品页再返回,也可以在广告列表页卸载时保存状态:
useEffect(() => {
  return () => {
    const scrollPosition = window.scrollY;
    sessionStorage.setItem('adListState', JSON.stringify({
      scrollPosition,
      loadedAds: [...ads]
    }));
  };
}, [ads]);

方案三:自定义路由监听与全局状态管理

如果你的应用比较复杂,有多个类似的无限滚动页面,可以用全局状态管理(比如Context API、Redux)结合路由监听来统一处理:

  1. 创建全局状态存储滚动和数据信息:
import { createContext, useContext, useState } from 'react';

const ScrollRestoreContext = createContext();

export const ScrollRestoreProvider = ({ children }) => {
  const [pageStates, setPageStates] = useState({});

  // 保存页面状态
  const savePageState = (pathname, state) => {
    setPageStates(prev => ({ ...prev, [pathname]: state }));
  };

  // 获取页面状态
  const getPageState = (pathname) => {
    return pageStates[pathname];
  };

  return (
    <ScrollRestoreContext.Provider value={{ savePageState, getPageState }}>
      {children}
    </ScrollRestoreContext.Provider>
  );
};

export const useScrollRestore = () => useContext(ScrollRestoreContext);
  1. 在广告列表页使用全局状态:
import { useLocation, useEffect } from 'react-router-dom';
import { useScrollRestore } from './ScrollRestoreContext';

const AdList = () => {
  const location = useLocation();
  const { savePageState, getPageState } = useScrollRestore();
  const [ads, setAds] = useState([]);

  // 组件挂载时恢复状态
  useEffect(() => {
    const savedState = getPageState(location.pathname);
    if (savedState) {
      setAds(savedState.loadedAds);
      setTimeout(() => {
        window.scrollTo(0, savedState.scrollPosition);
      }, 0);
    }
  }, [location.pathname, getPageState]);

  // 跳转前保存状态
  const handleAdClick = (adId) => {
    const scrollPosition = window.scrollY;
    savePageState(location.pathname, {
      scrollPosition,
      loadedAds: [...ads]
    });
    navigate(`/product/${adId}`);
  };

  // 无限滚动加载逻辑...
};

注意事项:

  • 用setTimeout包裹window.scrollTo是为了确保DOM已经渲染了恢复后的广告列表,否则滚动位置可能不准确。
  • 如果使用sessionStorage,注意数据的大小限制,避免存储过多广告数据导致问题。
  • 全局状态方案适合多页面复用场景,能减少重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:57:20