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

React实现返回上一页时定位到原滚动位置的方案

在ReactJS中实现页面返回时精准定位到滚动位置的方案

下面提供几种实用的实现思路,覆盖普通列表和虚拟列表场景:

方法一:利用路由状态存储滚动位置

通过React Router的state属性传递跳转前的滚动位置,返回页面时读取该状态并恢复滚动:

代码示例(React Router v6)

import { useNavigate, useLocation } from 'react-router-dom';

const PageA = () => {
  const navigate = useNavigate();
  const location = useLocation();

  // 点击列表行跳转时保存滚动位置
  const handleRowClick = (rowId) => {
    const currentScrollY = window.scrollY;
    navigate(`/detail/${rowId}`, { state: { scrollY: currentScrollY } });
  };

  // 组件挂载/路由状态更新时恢复滚动位置
  useEffect(() => {
    if (location.state?.scrollY) {
      window.scrollTo(0, location.state.scrollY);
    }
  }, [location]);

  return (
    <div className="long-list">
      {/* 超长列表渲染,示例为1000行 */}
      {Array.from({ length: 1000 }).map((_, index) => (
        <div 
          key={index} 
          className="list-row" 
          onClick={() => handleRowClick(index)}
        >
          第{index + 1}行 - 点击查看详情
        </div>
      ))}
    </div>
  );
};

如果用Link组件,可直接通过to属性的state传递:

<Link 
  to={{
    pathname: `/detail/${rowId}`,
    state: { scrollY: window.scrollY }
  }}
>
  查看详情
</Link>

方法二:虚拟列表场景的精准定位

如果页面A使用虚拟列表(如react-window/react-virtualized),直接存储窗口滚动位置可能不准确,需保存目标行的索引,通过虚拟列表自身方法滚动:

代码示例(react-window)

import { FixedSizeList as List } from 'react-window';
import { useNavigate, useLocation } from 'react-router-dom';
import { useRef, useEffect } from 'react';

const PageA = () => {
  const navigate = useNavigate();
  const location = useLocation();
  const listRef = useRef(null);

  // 跳转时保存目标行索引
  const handleRowClick = (rowIndex) => {
    navigate(`/detail/${rowIndex}`, { state: { targetRowIndex: rowIndex } });
  };

  // 返回时滚动到目标行
  useEffect(() => {
    if (location.state?.targetRowIndex && listRef.current) {
      listRef.current.scrollToItem(location.state.targetRowIndex);
    }
  }, [location]);

  return (
    <List
      ref={listRef}
      height={600}
      itemCount={1000}
      itemSize={50}
      width="100%"
    >
      {({ index, style }) => (
        <div 
          style={style} 
          className="virtual-list-row"
          onClick={() => handleRowClick(index)}
        >
          虚拟列表第{index + 1}行
        </div>
      )}
    </List>
  );
};

方法三:用sessionStorage持久化滚动位置

若担心路由状态丢失(比如用户刷新页面),可使用sessionStorage存储滚动信息,返回后读取并清除:

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

const PageA = () => {
  const navigate = useNavigate();

  const handleRowClick = (rowId) => {
    const scrollY = window.scrollY;
    sessionStorage.setItem('pageAScrollPos', scrollY.toString());
    navigate(`/detail/${rowId}`);
  };

  useEffect(() => {
    const savedPos = sessionStorage.getItem('pageAScrollPos');
    if (savedPos) {
      window.scrollTo(0, parseInt(savedPos));
      sessionStorage.removeItem('pageAScrollPos');
    }
  }, []);

  // 列表渲染逻辑...
};

注意事项

  • 如果页面A存在路由参数变化(如筛选条件更新),需增加判断逻辑,避免在参数变更时错误恢复旧的滚动位置。
  • 虚拟列表场景优先使用组件自身的滚动方法,比window.scrollTo更精准,因为虚拟列表仅渲染可见区域DOM。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:01:05