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

如何用React/TypeScript实现移动端与桌面端帖子列表无限滚动

React/TypeScript 实现帖子无限滚动

实现思路

  • 初始显示10条帖子,通过状态控制当前渲染的数量
  • 使用Intersection Observer API监听最后一条可见帖子的位置,当它进入视口时自动加载下一批10条
  • 确保加载数量不会超过帖子总数

修改后的完整代码

import { useState, useEffect, useRef } from 'react';
import PostStyles from "../../../components/ui/createPost/_createpost.module.scss"
import CreatePost from "../createPost/createPost"
import Post from "../post/post"
import Modal from "../createPost/Modal"
import { postType } from "../../../util/types"

type mainSectionType = {
  posts: postType[]
}

const MainSection = ({ posts }: mainSectionType) => {
  // 控制当前显示的帖子数量,初始为10
  const [visiblePostsCount, setVisiblePostsCount] = useState(10);
  // 最后一个帖子的DOM引用,用于监听滚动
  const lastPostRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const [entry] = entries;
        // 当最后一个帖子进入视口时,加载下一批
        if (entry.isIntersecting && visiblePostsCount < posts.length) {
          setVisiblePostsCount(prev => Math.min(prev + 10, posts.length));
        }
      },
      { threshold: 0.1 }
    );

    const currentRef = lastPostRef.current;
    if (currentRef) {
      observer.observe(currentRef);
    }

    // 清理监听
    return () => {
      if (currentRef) {
        observer.unobserve(currentRef);
      }
    };
  }, [visiblePostsCount, posts.length]);

  // 获取当前需要渲染的帖子列表
  const visiblePosts = posts.slice(0, visiblePostsCount);

  return (
    <>
      <Modal />
      <div className={PostStyles.post__create_postContainer}>
        <CreatePost />
      </div>
      <div className={PostStyles.post__posts_container}>
        {visiblePosts.map((post, index) => {
          // 给最后一个可见帖子添加ref
          const isLastPost = index === visiblePosts.length - 1;
          return (
            <div key={post._id} ref={isLastPost ? lastPostRef : null}>
              <Post
                post_desc={post.post_description}
                postID={post._id}
                username={post.creator.name}
                timeposted={post.time_posted}
                userImg={post.creator.profilePicture}
                photos={post.photos}
              />
            </div>
          );
        })}
        {/* 如果还有未加载的帖子,显示加载提示 */}
        {visiblePostsCount < posts.length && (
          <div style={{ textAlign: 'center', padding: '1rem' }}>
            加载中...
          </div>
        )}
      </div>
    </>
  )
}

export default MainSection

关键部分说明

  1. 状态管理:visiblePostsCount负责控制当前渲染的帖子数量,每次加载递增10,同时用Math.min确保不会超过总帖子数
  2. Intersection Observer:通过监听最后一个帖子的可见性,避免了传统滚动事件的性能问题,只有当元素进入视口才触发加载
  3. 高效渲染:使用posts.slice(0, visiblePostsCount)只渲染当前需要展示的帖子,而不是一次性渲染全部
  4. key优化:将原来的index替换为post._id作为组件key,避免列表更新时的渲染问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:31:03