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

react-infinite-scroll-component的next函数仅触发一次问题求助

React Infinite Scroll Component仅触发一次next函数问题

组件实现代码

<div id="scrollableDiv" style={{ height: 300, overflow: "auto" }}>
       <InfiniteScroll
         dataLength={texts.length}
         next={getText}
         hasMore={true}
         loader={<h5>Loading...</h5>}
         endMessage={<p style={{textAlign:'center'}}><b>Yay! You've seen it all!</b></p>}
         scrollableTarget="scrollableDiv"
         >
         {<Texts texts = {texts}/>}
         </InfiniteScroll>
</div>

文本状态数组定义:

const [texts, setTexts] = useState([])

getText方法实现

const getText = async ()=>{
        const res = await axios.get("http://localhost:3001/api/sth",{
            params: {
                ids: followings.map(i => i.id),
                str_ids: followings.map(i => i.str_id)
              },
              paramsSerializer: params => {
                return qs.stringify(params)
              }
        });

        let str_ids_res = res.data.map(i => i.string_id)
        let texts_res = res.data.map(i => i.texts)
        console.log(texts_res)

        const filtered_res = // some processing here on texts_res
        /* eslint eqeqeq: 0 */
        if(!arrayIsEqual(filtered_res,texts)){
            console.log("Not equal")
            // append arrays to a array state
            setTexts((prevtexts) => prevtexts.concat([...filtered_res]))
        }
    }

注:接口http://localhost:3001/api/sth每次都会返回两条不同的文本,理论上setTexts每次都会被调用

Texts子组件代码

const Texts = ({texts}) =>{
    return (
        <>
            {texts.map(text =>(
                <div key={text.id}>
                    <Card>
                        <Card.Content>
                            <Card.Description>
                            {text.full_text}
                            </Card.Description>
                        </Card.Content>
                    </Card>
                </div>
            ))}
        </>
    );
}

问题现象

尽管dataLength变量设置正确,但InfiniteScroll组件仅触发一次next函数。初始时texts为空,启动应用后仅显示'Loading....'。

解决方案

1. 排查arrayIsEqual函数逻辑

自定义的arrayIsEqual可能存在判断错误,导致新返回的数据被误判为与现有texts相等,跳过setTexts。可以临时注释掉该判断,直接执行setTexts,验证是否能触发多次加载。

2. 确认dataLength的更新

添加日志确认texts.length是否在每次setTexts后正确更新:

console.log('当前texts长度:', texts.length)

如果长度未变化,说明setTexts没有正确执行,需要检查数据处理逻辑。

3. 检查滚动容器与内容高度

如果内容总高度始终未超过滚动容器的300px,组件不会触发加载更多。可以:

  • 给Card添加固定高度样式(如style={{height: 100}}),强制内容高度超出容器
  • 检查Card组件是否正确渲染,是否存在样式导致高度为0的情况

4. 调整hasMore的控制逻辑

虽然接口返回新数据,但可以用状态动态控制hasMore,避免硬编码为true:

const [hasMore, setHasMore] = useState(true);

// 在getText中
const getText = async ()=>{
    const res = await axios.get(...);
    // ...数据处理
    if(filtered_res.length === 0){
        setHasMore(false);
    }
    setTexts(prev => prev.concat(filtered_res));
}

// 组件中
<InfiniteScroll
    hasMore={hasMore}
    // 其他属性
>

5. 验证scrollableTarget的有效性

尝试移除scrollableTarget属性,让组件监听window滚动,排查是否是滚动容器引用失败的问题。如果window滚动能触发多次加载,说明原容器的DOM引用存在问题,需要确认scrollableDiv是否正确渲染。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 11:57:10