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

React集成SWAPI实现无限滚动问题:无法加载更多页面求助

问题分析与修改方案

你的代码存在几个核心问题导致无法加载更多数据:

  • fetchPeople函数的问题:

    1. 提前定义的peopleApi会在组件每次渲染时创建,但它依赖的page变量不会动态更新,而且fetchPeople每次调用都会用初始的page=1的请求。
    2. fetchPeople直接用setPeople(transformPeople)覆盖现有数据,没有实现追加逻辑。
    3. fetchPeople没有返回API响应里的next分页链接,导致getMorePeople无法获取下一页地址。
  • getMorePeople函数的逻辑错误:

    1. 调用fetchPeople(people)时,fetchPeople并不接受参数,也不会返回{next, results},导致解构报错。
    2. 递归调用的方式不适合React组件,应该通过更新state来触发新的请求,而不是递归返回数据。
    3. 点击按钮时,getMorePeople没有正确关联组件的page或next状态。
  • useEffect依赖缺失:
    初始的useEffect只执行一次,没有监听page或next的变化,无法触发新的请求。


修改后的完整代码

import { useEffect, useState } from "react";
import axios from "axios";

const swapi = axios.create({
    baseURL: "https://swapi.dev/api/"
});

const InfiniteScroll = () => {
    const [people, setPeople] = useState([]);
    const [nextPageUrl, setNextPageUrl] = useState("people/?page=1");
    const [isLoading, setIsLoading] = useState(false);

    // 封装通用的获取人物数据函数,接收请求地址,返回处理后的数据和下一页地址
    const fetchPeople = async (url) => {
        setIsLoading(true);
        try {
            const response = await swapi.get(url);
            const transformedPeople = response.data.results.map(person => ({
                name: person.name,
                height: person.height,
                hair_color: person.hair_color,
                skin_color: person.skin_color,
                birth_year: person.birth_year
            }));
            return {
                data: transformedPeople,
                next: response.data.next
            };
        } catch (err) {
            console.error("获取数据失败:", err);
            return { data: [], next: null };
        } finally {
            setIsLoading(false);
        }
    };

    // 初始加载第一页数据
    useEffect(() => {
        const loadInitialData = async () => {
            const { data, next } = await fetchPeople(nextPageUrl);
            setPeople(data);
            setNextPageUrl(next);
        };
        loadInitialData();
    }, []);

    // 加载更多数据的函数
    const getMorePeople = async () => {
        if (!nextPageUrl || isLoading) return; // 没有下一页或正在加载时不触发请求

        const { data, next } = await fetchPeople(nextPageUrl);
        setPeople(prevPeople => [...prevPeople, ...data]); // 追加新数据
        setNextPageUrl(next);
    };

    return (
        <>
            <div>
                {people.map((onePerson) => (
                    <div key={onePerson.name}>
                        <p>{onePerson.name}</p>
                        <p>Height: {onePerson.height}</p>
                        <p>Hair color: {onePerson.hair_color}</p>
                        <p>Skin color: {onePerson.skin_color}</p>
                        <p>Birth year: {onePerson.birth_year}</p>
                    </div>
                ))}
                <button 
                    onClick={getMorePeople} 
                    disabled={!nextPageUrl || isLoading}
                >
                    {isLoading ? "加载中..." : nextPageUrl ? "加载更多" : "没有更多数据"}
                </button>
            </div>
        </>
    );
};

export default InfiniteScroll;

关键改动说明

  1. 用nextPageUrl代替page状态:直接存储API返回的next链接,避免手动计算页码,适配SWAPI的分页机制。
  2. 重构fetchPeople:让它接收请求地址,返回处理后的数据和下一页链接,同时添加加载状态和错误处理。
  3. 修改数据更新逻辑:使用setPeople(prevPeople => [...prevPeople, ...data])来追加新数据,而不是覆盖原有数据。
  4. 修正getMorePeople:直接利用nextPageUrl发起请求,更新state,去掉错误的递归逻辑,同时添加加载状态的判断,防止重复请求。
  5. 优化按钮状态:根据是否有下一页和加载状态,禁用按钮并显示对应文本,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:05:31