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

如何用React Router的Await实现点击加载更多国家数据的组件渲染

问题描述

需求为实现国家数据分批加载:首次加载8条数据,点击「显示更多」按钮时加载下8条,已加载数据需保留在页面中(类无限滚动,改用按钮触发),API地址为https://restcountries.com/v3.1/all。现有代码尝试通过useState及拆分Suspense/Await组件实现,但未达到预期效果。

解决方案

核心思路:由于目标API不支持分页参数,先获取全部数据后,通过状态控制渲染的条目数量范围,同时处理数据加载完成后的按钮隐藏逻辑。

修改后的完整代码:

import React, { Suspense, useState } from "react";
import { getAllCountries } from "../api/api";
import { defer, useLoaderData, Await } from "react-router-dom";
import CountryCard from "../components/CountryCard";
import Button from "../components/Button";
import ShowMoreIcon from "../components/Icons/ShowMoreIcon";
import Loading from "../components/Loading";

export const loader = async () => {
  const countries = getAllCountries();
  return defer({ countries });
};

const NUM_TO_ADD = 8;
const CountriesPage = () => {
  const { countries } = useLoaderData();
  // 用visibleCount控制显示的条目总数,初始为8
  const [visibleCount, setVisibleCount] = useState(NUM_TO_ADD);

  const showMoreHandler = () => {
    setVisibleCount(prev => prev + NUM_TO_ADD);
  };

  return (
    <main className="px-16 xl:px-0 xl:mx-auto max-w-7xl">
      <div className="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-6 lg:gap-12 mb-12">
        <Suspense fallback={<Loading />}>
          <Await resolve={countries}>
            {(data) => {
              // 截取前visibleCount条数据渲染
              const visibleCountries = data.slice(0, visibleCount);
              return visibleCountries.map((country) => (
                <CountryCard
                  key={country.name.common}
                  countryCapital={country.capital}
                  countryFlag={country.flags.png}
                  countryPopulation={country.population}
                  countryRegion={country.region}
                  countryId={country.cca3}
                  countryName={country.name.common}
                />
              ));
            }}
          </Await>
        </Suspense>
      </div>
      {/* 仅当显示数量小于总数据量时,显示「显示更多」按钮 */}
      <Suspense fallback={<></>}>
        <Await resolve={countries}>
          {(data) => (
            visibleCount < data.length && (
              <Button onClick={showMoreHandler} className="mx-auto flex items-center">
                <ShowMoreIcon />
                Show More
              </Button>
            )
          )}
        </Await>
      </Suspense>
    </main>
  );
};

export default CountriesPage;

关键改动说明

  • 将start/end状态替换为visibleCount,更直观控制显示的条目总数,避免范围计算出错
  • 在Await回调中通过slice(0, visibleCount)截取需渲染的数据,确保每次仅显示指定数量的条目
  • 为「显示更多」按钮添加判断逻辑:仅当visibleCount小于总数据量时才显示,避免数据加载完成后按钮仍存在
  • 调整Loading组件的导入位置,符合代码规范

补充说明

若后续API支持分页参数(如page/limit),可优化为点击按钮时请求下一页数据,将新数据追加到已加载列表中,进一步节省带宽。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:35:30