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

同一页面SSR与CSR共用数据集的实现方案及优化咨询

Markdown 格式用法示例

标题层级

一级标题(页面主标题)

二级标题(板块标题)

三级标题(子板块标题)

无序列表

  • 日常任务清单
  • 学习计划
    • 掌握Next.js SSR/CSR混合模式
    • 熟悉react-query无限滚动API

文本强调

需要重点关注的细节
核心实现步骤
必须避免的潜在问题

代码展示

单行命令:npx create-next-app@latest

业务代码示例:

import { useInfiniteQuery } from '@tanstack/react-query';
import { useEffect, useState } from 'react';

const Gallery = ({ initialData }) => {
  const [filters, setFilters] = useState({ category: '' });
  
  const { data, fetchNextPage, hasNextPage, refetch } = useInfiniteQuery({
    queryKey: ['gallery', filters],
    queryFn: ({ pageParam = 1 }) => 
      fetch(`/api/gallery?page=${pageParam}&limit=20&${new URLSearchParams(filters)}`).then(res => res.json()),
    initialData: { pages: [initialData], pageParams: [1] },
    getNextPageParam: (lastPage) => lastPage.nextPage ?? undefined,
  });

  // 滚动监听触发下一页请求
  useEffect(() => {
    const handleScroll = () => {
      const scrollBottom = window.innerHeight + document.documentElement.scrollTop;
      const pageHeight = document.documentElement.offsetHeight;
      if (scrollBottom >= pageHeight - 200 && hasNextPage) {
        fetchNextPage();
      }
    };
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [hasNextPage, fetchNextPage]);

  // 筛选条件变更时自动重新请求
  const handleFilterChange = (newFilters) => {
    setFilters(newFilters);
  };

  return (
    <div className="gallery-container">
      <div className="filter-bar">
        <select onChange={(e) => handleFilterChange({ category: e.target.value })}>
          <option value="">全部分类</option>
          <option value="nature">自然</option>
          <option value="city">城市</option>
        </select>
      </div>
      <div className="gallery-grid">
        {data.pages.flatMap(page => page.items.map(item => (
          <div key={item.id} className="gallery-item">
            <img src={item.imageUrl} alt={item.title} />
            <p>{item.title}</p>
          </div>
        )))}
      </div>
      {hasNextPage && <div className="loading">加载中...</div>}
    </div>
  );
};

// SSR 获取初始20条数据
export async function getServerSideProps() {
  const initialData = await fetch(`/api/gallery?page=1&limit=20`).then(res => res.json());
  return { props: { initialData } };
}

export default Gallery;

引用内容

SSR加载初始数据能提升首屏性能,但要注意初始数据与后续CSR数据的格式一致性,避免拼接时出现结构差异。
筛选条件变更时,react-query会自动根据新的queryKey重新发起请求,无需手动清空状态。

链接

react-query 无限滚动核心文档

图片

画廊布局示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:57:18