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

Next.js 13无限滚动:返回时保留数据与滚动位置方案咨询

在Next.js 13中恢复无限滚动的已加载数据与滚动位置

恢复滚动位置

结合sessionStorage和Next.js路由事件,就能实现离开页面时保存滚动位置、返回时自动恢复的效果:

'use client';
import { useEffect } from 'react';
import { usePathname, useRouter } from 'next/navigation';

export default function InfiniteScrollList() {
  const pathname = usePathname();
  const router = useRouter();

  // 离开页面时保存滚动高度
  useEffect(() => {
    const saveScrollPos = () => {
      sessionStorage.setItem(`scroll_pos_${pathname}`, window.scrollY.toString());
    };

    // 监听浏览器刷新/关闭、路由跳转(比如进入详情页)
    window.addEventListener('beforeunload', saveScrollPos);
    router.events.on('routeChangeStart', saveScrollPos);

    return () => {
      window.removeEventListener('beforeunload', saveScrollPos);
      router.events.off('routeChangeStart', saveScrollPos);
    };
  }, [pathname, router]);

  // 页面挂载时恢复滚动位置
  useEffect(() => {
    const savedPos = sessionStorage.getItem(`scroll_pos_${pathname}`);
    if (savedPos) {
      window.scrollTo(0, parseInt(savedPos, 10));
    }
  }, [pathname]);

  // 你的无限滚动逻辑
  return <div>...</div>;
}

保留已加载数据

不推荐用Cookies:Cookies最大容量仅4KB,无限滚动的数据很快会超出限制,且每次HTTP请求都会携带Cookies,浪费带宽。更合理的方案是用sessionStorage存储已加载条目:

'use client';
import { useState, useEffect } from 'react';
import { loadMoreItems } from '@/actions'; // 你的Server Action

export default function InfiniteScrollList() {
  const [items, setItems] = useState([]);
  const [currentPage, setCurrentPage] = useState(1);

  // 页面挂载时恢复已保存的数据和页码
  useEffect(() => {
    const savedItems = sessionStorage.getItem('infinite_scroll_items');
    const savedPage = sessionStorage.getItem('infinite_scroll_page');
    
    if (savedItems) {
      setItems(JSON.parse(savedItems));
      setCurrentPage(parseInt(savedPage) || 1);
    }
  }, []);

  // 数据更新时同步保存到sessionStorage
  useEffect(() => {
    sessionStorage.setItem('infinite_scroll_items', JSON.stringify(items));
    sessionStorage.setItem('infinite_scroll_page', currentPage.toString());
  }, [items, currentPage]);

  // 调用Server Action加载更多数据
  const loadMore = async () => {
    const newItems = await loadMoreItems(currentPage);
    setItems(prev => [...prev, ...newItems]);
    setCurrentPage(prev => prev + 1);
  };

  // 无限滚动触发逻辑(Intersection Observer示例)
  useEffect(() => {
    const loader = document.getElementById('load-more-trigger');
    if (!loader) return;

    const observer = new IntersectionObserver(entries => {
      if (entries[0].isIntersecting) loadMore();
    });

    observer.observe(loader);
    return () => observer.disconnect();
  }, [currentPage]);

  return (
    <div className="list-container">
      {items.map(item => (
        <div key={item.id} className="list-item">{item.content}</div>
      ))}
      <div id="load-more-trigger" className="loader">加载中...</div>
    </div>
  );
}

额外注意事项

  • 数据清理:sessionStorage会在用户关闭标签页后自动清除数据;如果需要手动清理,可在特定操作(如登出)时调用sessionStorage.removeItem('infinite_scroll_items')。
  • 数据一致性:若Server返回的数据可能更新,可在页面挂载时对比数据的最新更新时间,必要时重新拉取初始数据,避免展示过期内容。
  • Pages Router适配:如果使用Pages Router,useRouter需从next/router导入,路由事件监听逻辑保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:36:33