React Native对接ExerciseDB API:limit参数失效,需实现下拉加载更多
解决ExerciseDB API分页加载问题及滚动加载更多实现
问题分析
你遇到的limit参数无效,是因为ExerciseDB API的/exercises端点需要配合offset参数实现分页,仅传limit不会生效;同时当前实现会直接覆盖现有数据,无法实现加载更多的追加逻辑。
修复步骤
1. 改造useFetch Hook,支持分页与数据追加
修改你的useFetch hook,增加偏移量状态、加载更多逻辑,并调整数据更新方式:
import { useState, useEffect } from "react"; import axios from "axios"; const useFetch = (endpoint, limit) => { const [data, setData] = useState([]); const [offset, setOffset] = useState(0); const [isLoading, setIsLoading] = useState(false); const [isLoadingMore, setIsLoadingMore] = useState(false); const [error, setError] = useState(null); const [hasMore, setHasMore] = useState(true); const options = { method: 'GET', url: `https://exercisedb.p.rapidapi.com/${endpoint}?limit=${limit}&offset=${offset}`, headers: { 'X-RapidAPI-Key': API, 'X-RapidAPI-Host': 'exercisedb.p.rapidapi.com' }, }; const fetchData = async (isLoadMore = false) => { if (isLoadMore) setIsLoadingMore(true); else setIsLoading(true); try { const response = await axios.request(options); // 加载更多时追加数据,初始加载时替换 if (isLoadMore) { setData(prev => [...prev, ...response.data]); // 返回数据少于limit则标记无更多数据 if (response.data.length < limit) setHasMore(false); } else { setData(response.data); setHasMore(response.data.length === limit); } } catch (error) { setError(error); alert('加载失败'); } finally { if (isLoadMore) setIsLoadingMore(false); else setIsLoading(false); } } useEffect(() => { fetchData(); }, [endpoint, limit, offset]); const loadMore = () => { if (hasMore && !isLoadingMore) { setOffset(prev => prev + limit); } } const refetch = () => { setOffset(0); setHasMore(true); fetchData(); } return { data, isLoading, isLoadingMore, error, hasMore, loadMore, refetch }; } export default useFetch;
2. 使用FlatList实现滚动加载更多
修改Searchworkouts组件,用FlatList替代普通View渲染列表,利用onEndReached触发加载更多:
import { View, Text, TouchableOpacity, ActivityIndicator, FlatList } from 'react-native' import { useRouter } from 'expo-router' import styles from './searchworkouts.style' import { COLORS, SIZES } from '../../../constants' import WorkoutCard from '../../common/cards/workout/WorkoutCard' import useFetch from '../../../hook/useFetch'; const Searchworkouts = () => { const router = useRouter(); const { data, isLoading, isLoadingMore, error, hasMore, loadMore } = useFetch('exercises', 10); const renderFooter = () => { if (!hasMore) return null; return ( <View style={styles.loadingMoreContainer}> <ActivityIndicator size="small" color={COLORS.primary} /> </View> ); } return ( <View style={styles.container}> <View style={styles.header}> <Text style={styles.headerTitle}>Workouts</Text> <TouchableOpacity> <Text style={styles.headerBtn}>Show all</Text> </TouchableOpacity> </View> {isLoading ? ( <ActivityIndicator size="large" color={COLORS.primary} style={styles.loadingIndicator} /> ) : error ? ( <Text style={styles.errorText}>加载出错了</Text> ) : ( <FlatList data={data} keyExtractor={(item) => item.id} // 替换为你数据中实际的唯一标识字段 renderItem={({ item }) => <WorkoutCard workout={item} />} // 传递数据给卡片组件 contentContainerStyle={styles.cardsContainer} onEndReached={loadMore} onEndReachedThreshold={0.1} // 距离底部10%时触发加载 ListFooterComponent={renderFooter} /> )} </View> ) } export default Searchworkouts
关键说明
- 分页参数:ExerciseDB API要求同时传递
limit(每页数量)和offset(跳过的数据条数),仅传limit会返回全部数据。 - 数据追加:加载更多时将新数据合并到现有数组,而非直接替换,实现滚动加载的连续列表。
- 滚动触发:通过
FlatList的onEndReached属性,在用户滚动到列表底部附近时自动触发加载更多逻辑。 - 边界处理:当返回数据量小于设定的
limit时,标记为无更多数据,避免无效请求;区分初始加载和加载更多状态,优化用户体验。
内容的提问来源于stack exchange,提问作者0x1dsawdwae
相关产品推荐
相关产品推荐

