如何用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
关键部分说明
- 状态管理:
visiblePostsCount负责控制当前渲染的帖子数量,每次加载递增10,同时用Math.min确保不会超过总帖子数 - Intersection Observer:通过监听最后一个帖子的可见性,避免了传统滚动事件的性能问题,只有当元素进入视口才触发加载
- 高效渲染:使用
posts.slice(0, visiblePostsCount)只渲染当前需要展示的帖子,而不是一次性渲染全部 - key优化:将原来的
index替换为post._id作为组件key,避免列表更新时的渲染问题
内容的提问来源于stack exchange,提问作者Orisfina
相关产品推荐
相关产品推荐

