使用React实现书架无限滚动加载 首次渲染9本滚动到底部自动加载更多
问题原因分析
你编写的CallBooks组件无法正常运行的核心问题如下:
- 循环条件写反:初始
Load=0,Load>props.number永远不成立,函数无返回值,无内容渲染 - 循环内提前return:即使条件成立,第一次循环就会return单个Book组件,后续的
SetLoad逻辑永远不会执行,无法生成多个组件 - React不支持通过循环中多次return的方式渲染列表,需要返回包含多个子元素的集合
实现方案
1. 修正CallBooks组件
接收count参数,渲染指定数量的Book组件,代码如下:
import React from "react"; import Book from './Book'; const CallBooks = (props) => { return ( <> {Array.from({ length: props.count }, (_, index) => ( <Book key={index} number={index} /> ))} </> ); }; export default CallBooks;
提示:如果Book.json里有书籍的唯一id,建议用id作为key替换index,渲染性能更好。
2. 实现无限滚动逻辑
在BookFeed组件中实现滚动监听、自动加载逻辑,首次渲染9本,滚动到底部自动加载更多,代码如下:
import React, { useState, useEffect, useCallback } from "react"; import CallBooks from './CallBooks'; import './Book.css'; import Books from "./Book.json"; const BookFeed = () => { // 初始渲染9本 const [renderCount, setRenderCount] = useState(9); // 加载状态防止重复触发加载 const [isLoading, setIsLoading] = useState(false); // 书籍总数量 const totalBooks = Books.length; const handleScroll = useCallback(() => { // 加载中或者已经加载完全部书籍直接终止逻辑 if (isLoading || renderCount >= totalBooks) return; // 计算滚动位置,提前50px触发加载体验更顺滑 const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; const clientHeight = document.documentElement.clientHeight; const scrollHeight = document.documentElement.scrollHeight; if (scrollTop + clientHeight >= scrollHeight - 50) { setIsLoading(true); // 模拟接口请求延迟,本地数据可以直接删除setTimeout setTimeout(() => { // 每次加载3本,可自行调整数值 setRenderCount(prev => Math.min(prev + 3, totalBooks)); setIsLoading(false); }, 300); } }, [isLoading, renderCount, totalBooks]); // 绑定/解绑滚动监听事件 useEffect(() => { window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, [handleScroll]); return ( <div className='books'> <CallBooks count={renderCount} /> {isLoading && <div className="loading">加载中...</div>} {renderCount >= totalBooks && <div className="no-more">没有更多书籍了</div>} </div> ); }; export default BookFeed;
内容的提问来源于stack exchange,提问作者kizaru13
相关产品推荐
相关产品推荐

