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

如何用Axios、useState和useEffect实现多页面数据获取及加载更多

实现Rick and Morty API的加载更多功能

问题分析

你的现有代码仅能获取单页数据,要实现加载更多并存储全量数据用于后续筛选,需要补充下一页链接跟踪、数据追加逻辑,同时调整状态的初始类型(原代码用对象存储数组数据不合适)。

修改后完整代码

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

function CharacterList() {
  // 存储所有已加载的角色数据(数组类型,初始为空数组)
  const [characters, setCharacters] = useState([]);
  // 用于筛选后的展示数据
  const [filtered, setFiltered] = useState([]);
  // 存储下一页的API链接(从接口返回的info.next字段获取)
  const [nextPageUrl, setNextPageUrl] = useState(null);
  // 加载状态,防止重复点击加载按钮
  const [isLoading, setIsLoading] = useState(false);
  const baseUrl = 'https://rickandmortyapi.com/api/character/';

  // 初始加载第一页数据
  useEffect(() => {
    fetchPage(baseUrl);
  }, []);

  // 封装通用的分页请求函数
  const fetchPage = async (url) => {
    setIsLoading(true);
    try {
      const res = await axios.get(url);
      // 将新页数据追加到已有数据末尾
      setCharacters(prev => [...prev, ...res.data.results]);
      // 同步更新筛选数据(无筛选条件时直接复用全量数据)
      setFiltered(prev => [...prev, ...res.data.results]);
      // 保存下一页链接,无更多数据时为null
      setNextPageUrl(res.data.info.next);
    } catch (error) {
      console.error('加载数据失败:', error);
    } finally {
      setIsLoading(false);
    }
  };

  // 加载更多按钮点击事件
  const handleLoadMore = () => {
    if (nextPageUrl && !isLoading) {
      fetchPage(nextPageUrl);
    }
  };

  return (
    <div>
      {/* 角色列表展示 */}
      <div className="character-list">
        {filtered.map(character => (
          <div key={character.id} className="character-card">
            <img src={character.image} alt={character.name} />
            <h3>{character.name}</h3>
            <p>状态: {character.status}</p>
          </div>
        ))}
      </div>

      {/* 加载更多按钮:无下一页或加载中时禁用 */}
      <button 
        onClick={handleLoadMore} 
        disabled={!nextPageUrl || isLoading}
        style={{ marginTop: '20px', padding: '10px 20px' }}
      >
        {isLoading ? '加载中...' : '加载更多'}
      </button>
    </div>
  );
}

export default CharacterList;

关键修改点说明

  • 状态调整:
    • 将characters和filtered的初始值改为空数组,匹配接口返回的results数组类型
    • 新增nextPageUrl跟踪下一页接口地址,无需手动计算页码(API返回的info.next直接提供下一页链接)
    • 新增isLoading状态避免重复发起请求
  • 数据追加逻辑:使用setCharacters(prev => [...prev, ...newData])将新页数据追加到已有数据后,保留全量数据用于后续筛选
  • 通用请求封装:把分页请求封装成fetchPage函数,初始加载和加载更多逻辑复用,减少冗余代码
  • 按钮交互优化:根据nextPageUrl和isLoading状态禁用按钮,避免无效点击

后续筛选扩展示例

当需要添加筛选功能时,只需基于全量的characters数据过滤,更新filtered状态即可,比如按名字筛选:

// 按名字筛选示例
const handleFilterByName = (keyword) => {
  const filteredData = characters.filter(character => 
    character.name.toLowerCase().includes(keyword.toLowerCase())
  );
  setFiltered(filteredData);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 08:50:29