React InfiniteScroll无限滚动失效 loadFunc未触发如何解决
问题描述
React项目中使用InfiniteScroll组件实现新闻列表无限滚动功能时,绑定的下一页加载方法loadFunc始终不执行,控制台无法输出预期调试日志testing,无限滚动功能完全失效。
故障根因
代码存在4处直接导致功能异常的问题:
state初始化缺失字段:构造函数中未定义totalArticlesResults初始值,首次渲染时该值为undefined,会干扰hasMore属性的判断逻辑。- 列表渲染逻辑错误:渲染列表时增加了
!this.state.loading的前置判断,加载状态切换时会直接卸载已渲染的列表节点,干扰InfiniteScroll组件内部对内容高度的计算,导致触底检测逻辑失效。 loadFunc存在语法与逻辑bug:- 合并新旧文章列表时错误添加了
this指向,写为this.parsedData.articles,函数执行时会直接抛出引用错误 - 加载完下一页数据后未更新
page状态值,就算触发加载也永远请求第2页数据 - 调用
data.json()时多余传入了data入参,不符合API规范
- 合并新旧文章列表时错误添加了
- InfiniteScroll组件配置不全:缺少加载完成提示、加载器容器配置,部分版本下会导致初始内容高度不足时自动加载逻辑不生效。
修复方案
按以下步骤逐一修正代码即可:
- 补全state初始字段,避免初始值异常
constructor(props) { super(props); this.state = { page: 1, articles: [], loading: false, totalArticlesResults: 0, // 补全总条目的初始值 }; }
- 修正componentDidMount中的json调用,移除多余入参
async componentDidMount() { const url = `https://newsapi.org/v2/top-headlines?country=us&category=${this.props.category}&apiKey=ff954e750b914328a0bc65c2e45304c4&page=1&pageSize=${this.props.pageSize}`; this.setState({ loading: true }); let data = await fetch(url); let parsedData = await data.json(); // 移除json方法多余的data入参 this.setState({ articles: parsedData.articles, totalArticlesResults: parsedData.totalResults, loading: false, }); }
- 重写loadFunc方法,修复逻辑错误
loadFunc = async () => { console.log('testing'); const nextPage = this.state.page + 1; const url = `https://newsapi.org/v2/top-headlines?country=us&category=${this.props.category}&apiKey=ff954e750b914328a0bc65c2e45304c4&page=${nextPage}&pageSize=${this.props.pageSize}`; this.setState({ loading: true }); let data = await fetch(url); let parsedData = await data.json(); this.setState({ articles: [...this.state.articles, ...parsedData.articles], // 移除parsedData前多余的this totalArticlesResults: parsedData.totalResults, loading: false, page: nextPage // 加载成功后更新当前页码 }) }
- 调整render方法内的列表渲染逻辑,补全InfiniteScroll组件配置
render() { return ( <div className="container my-3"> <InfiniteScroll dataLength={this.state.articles.length} next={this.loadFunc} hasMore={this.state.articles.length < this.state.totalArticlesResults} loader={<div className="text-center my-3"><Spinner /></div>} endMessage={ <p className="text-center my-3 text-muted"> <b>已经加载全部新闻</b> </p> } > <div className="container"> <div className="row"> {/* 移除!this.state.loading判断,已加载内容始终保持渲染 */} {this.state.articles.map((element, index) => { return ( <div className="col-md-4" key={index}> {/* 新闻卡片内容 */} </div> ); })} </div> </div> </InfiniteScroll> </div> ); }
修复后如果单页新闻高度不足以撑满浏览器视口,InfiniteScroll会自动触发下一页加载直到内容高度超过视口,滚动触底时也会正常执行loadFunc加载后续内容。
内容的提问来源于stack exchange,提问作者Bivishan Sapkota
相关产品推荐
相关产品推荐

