如何在React Native搭配Redux Saga实现FlatList加载更多功能
React Native + Redux Saga 实现FlatList上拉加载更多修复方案
核心问题梳理
现有代码存在几个明显问题:
- 变量拼写不一致:
useSelector返回的变量命名为listing,但FlatList中使用的是listings,会导致数据读取失败 loadMore方法仅修改了本地页码状态,没有触发Saga监听的GET_ADSaction发起新页请求- 之前尝试的数据拼接写法错误:
state.concat中state是存储对象,本身没有数组的concat方法,需要取state.data进行拼接 - 缺少加载状态判断,可能会触发重复的上拉加载请求
分步代码调整
2.1 调整SearchScreen逻辑
首先修正变量拼写,补充加载状态判断和请求触发逻辑:
// 从Redux中同时取数据和加载状态 const { data: listings, loading } = useSelector((state) => state.adData); // 首次进入页面触发第一页请求 useEffect(() => { dispatch({ type: Actions.GET_ADS, page: 1 }); }, [dispatch]) const loadMore = () => { // 加载中直接返回,避免重复请求 if (loading) return; const nextPage = pageCurrent + 1; setpageCurrent(nextPage); // 触发分页请求action,传递新页码 dispatch({ type: Actions.GET_ADS, page: nextPage }); }; // FlatList可选补充底部加载提示 <FlatList showsVerticalScrollIndicator={false} data={listings} keyExtractor={keyExtractor} removeClippedSubviews={true} onEndReached={loadMore} onEndReachedThreshold={0.8} windowSize={15} getItemLayout={getItemLayout} renderItem={renderItem} // 底部加载中提示 ListFooterComponent={() => loading ? <ActivityIndicator style={{ paddingVertical: 20 }} /> : null} />
2.2 调整Reducer数据拼接逻辑
首先确保初始状态的data为空数组,再修改成功回调的数据拼接逻辑:
// 初始状态示例 const initState = { data: [], loading: false } export default function productReducer( state = initState, { type, payload, error } ) { switch (type) { case Actions.GET_ADS: return { ...state, loading: true }; case Actions.GET_ADS_SUCCESS: return { ...state, // 新旧分页数据拼接 data: [...state.data, ...payload], loading: false }; case Actions.GET_PRODUCT_ATTRIBUTE_ERROR: return { ...state, loading: false, error }; default: return state; } }
如果需要支持下拉刷新功能,可以在请求action中加isRefresh标识,当isRefresh为true时直接用data: payload覆盖旧数据即可。
2.3 补充Saga监听配置
确保Saga正确监听GET_ADS action:
import { takeEvery } from 'redux-saga/effects'; function* fetchListingsSaga({ page }) { try { const data = yield call(getListings, { page }); yield put({ type: Actions.GET_ADS_SUCCESS, payload: data.data.response }); } catch (e) { yield put({ type: Actions.GET_PRODUCT_ATTRIBUTE_ERROR, error: e }); } } // 根Saga中添加监听 function* rootSaga() { yield takeEvery(Actions.GET_ADS, fetchListingsSaga); }
注意事项
- 确保分页接口返回的是当前页的数组格式数据,不要返回全量数据
keyExtractor必须使用列表项的唯一id作为key,不要使用数组下标,避免加载更多后列表渲染错乱- 若需要处理无更多数据的场景,可在Redux中新增
hasMore字段,接口返回总条数/是否有下一页标识后更新该字段,loadMore中判断hasMore为false时直接返回即可
内容的提问来源于stack exchange,提问作者arun
相关产品推荐
相关产品推荐

