React Router:如何返回上一页时恢复滚动位置
解决返回缩略页时定位到上次滚动位置的方案
这问题我之前做图片画廊项目时也碰到过,用户返回时回到顶部的体验确实很差。下面分享两种靠谱的实现思路,根据你的需求和技术栈选就行:
方案一:用 sessionStorage 持久化滚动位置(推荐)
这种方式能保留滚动位置,就算用户刷新页面也不会丢失,体验更友好。核心逻辑是:离开缩略页前保存滚动位置,返回时读取并恢复。
import { useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; const ThumbnailPage = () => { const [scrollPosition, setScrollPosition] = useState(0); // 监听滚动事件,实时记录当前位置 useEffect(() => { const handleScroll = () => { setScrollPosition(window.scrollY); }; window.addEventListener('scroll', handleScroll); // 组件挂载/返回时,恢复滚动位置 window.scrollTo(0, scrollPosition); // 组件卸载前,把位置存到 sessionStorage return () => { sessionStorage.setItem('thumbnailScrollPos', scrollPosition.toString()); window.removeEventListener('scroll', handleScroll); }; }, [scrollPosition]); // 首次挂载时,读取之前保存的位置 useEffect(() => { const savedPos = sessionStorage.getItem('thumbnailScrollPos'); if (savedPos) { const posNum = parseInt(savedPos, 10); setScrollPosition(posNum); window.scrollTo(0, posNum); } }, []); return ( <div className="thumbnail-list"> {/* 你的缩略图列表 */} {images.map(img => ( <Link key={img.id} to={`/fullscreen/${img.id}`}> <img src={img.thumbnail} alt={img.title} /> </Link> ))} </div> ); }; export default ThumbnailPage;
关键细节:
sessionStorage是会话级存储,关闭浏览器标签后才会清空,刚好匹配这种场景- 如果你的缩略页用了虚拟列表(比如
react-window),不要用window.scrollY,而是通过 ref 获取列表容器的scrollTop值
方案二:通过 React Router 的 state 传递滚动位置
如果不需要持久化(比如刷新页面不用保留位置),可以用路由的 state 临时传递滚动位置,适合轻量化场景。
1. 缩略页跳转时传递位置
<Link to={`/fullscreen/${img.id}`} // 把当前滚动位置作为路由 state 传递 state={{ scrollPos: window.scrollY }} > <img src={img.thumbnail} alt={img.title} /> </Link>
2. 全屏页返回时带回位置
import { Link, useLocation } from 'react-router-dom'; const FullscreenPage = () => { const location = useLocation(); return ( <div className="fullscreen-container"> <img src={currentImage.src} alt={currentImage.title} /> {/* 返回时把之前的滚动位置再传回去 */} <Link to="/thumbnails" state={{ scrollPos: location.state?.scrollPos || 0 }} > ← 返回缩略页 </Link> </div> ); };
3. 缩略页接收并恢复位置
import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; const ThumbnailPage = () => { const location = useLocation(); useEffect(() => { const scrollPos = location.state?.scrollPos; if (scrollPos !== undefined) { window.scrollTo(0, scrollPos); // 可选:清除 state,避免下次刷新页面还带着旧值 location.state = null; } }, [location]); // ... 其他代码 };
额外注意事项
- 如果你的缩略页是嵌套在其他布局组件里(比如有固定导航栏),计算滚动位置时要考虑导航栏高度,避免被遮挡
- 类组件的实现思路一致,把
useEffect换成componentDidMount、componentWillUnmount即可
内容的提问来源于stack exchange,提问作者yN.
相关产品推荐
相关产品推荐

