React Native:如何提取getUsers为独立模块并保留原有功能
解决方案
1. 提取getUsers到独立API模块
创建单独的业务逻辑模块(比如src/services/userService.js),将数据请求逻辑抽离,让它只负责网络请求和返回数据,不依赖组件内部状态:
// src/services/userService.js import axios from "axios"; export const getUsers = async (page, count) => { try { const res = await axios.get(`https://randomuser.me/api/?page=${page}&results=${count}`); return res.data.results; } catch (error) { console.error('获取用户数据失败:', error); throw error; // 抛出错误交由组件处理 } };
2. 修改Home组件,适配独立模块并修复跳转不刷新问题
在Home组件中导入独立模块,重新封装状态更新逻辑,同时解决页面返回后FlatList不刷新的问题:
// Home.js import React, { useEffect, useState } from "react"; import { View, Text, FlatList, Image, StyleSheet, ActivityIndicator, StatusBar, TouchableOpacity } from "react-native"; import { getUsers } from './services/userService'; // 导入独立模块 const Home = ({route, navigation}) => { const {count} = route.params; const [users, setUsers] = useState([]); const [currentPage, setCurrentPage] = useState(1); const [isLoading, setIsLoading] = useState(false); // 组件内封装数据加载逻辑,调用独立的getUsers函数 const fetchUsers = async () => { setIsLoading(true); try { const newUsers = await getUsers(currentPage, count); // 使用函数式更新避免闭包导致的状态错误 setUsers(prevUsers => [...prevUsers, ...newUsers]); } catch (error) { // 可在此添加错误提示,比如Toast弹窗 } finally { setIsLoading(false); } }; const renderItem = ({ item }) => { return ( <View style={styles.itemWrapperStyle}> <TouchableOpacity activeOpacity={0.5} onPress={() => navigation.navigate('Details', {it: item}) }> <Image style={styles.itemImageStyle} source={{ uri: item.picture.large }}/> </TouchableOpacity> <View style={styles.contentWrapperStyle}> <Text style={styles.txtNameStyle}>{`${item.name.title} ${item.name.first} ${item.name.last}`}</Text> <Text style={styles.txtEmailStyle}>{item.email}</Text> </View> </View> ); }; const renderLoader = () => { return isLoading ? ( <View style={styles.loaderStyle}> <ActivityIndicator size="large" color="#aaa" /> </View> ) : null; }; const loadMoreItem = () => { // 避免加载中重复触发请求 if (!isLoading) { setCurrentPage(prevPage => prevPage + 1); } }; // 监听页面聚焦,解决从Details返回后不刷新的问题 useEffect(() => { const unsubscribe = navigation.addListener('focus', () => { // 回到首页时重置数据并重新加载第一页 setUsers([]); setCurrentPage(1); fetchUsers(); }); return unsubscribe; // 组件卸载时清理监听 }, [navigation]); // 分页加载数据 useEffect(() => { fetchUsers(); }, [currentPage]); return ( <> <StatusBar backgroundColor="#000" /> <FlatList data={users} renderItem={renderItem} keyExtractor={item => item.email} ListFooterComponent={renderLoader} onEndReached={loadMoreItem} onEndReachedThreshold={0.1} // 调整阈值,提升加载体验 /> </> ); }; // 补充样式定义 const styles = StyleSheet.create({ itemWrapperStyle: { flexDirection: 'row', padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }, itemImageStyle: { width: 60, height: 60, borderRadius: 30 }, contentWrapperStyle: { marginLeft: 15, justifyContent: 'center' }, txtNameStyle: { fontSize: 16, fontWeight: 'bold' }, txtEmailStyle: { fontSize: 14, color: '#666', marginTop: 5 }, loaderStyle: { paddingVertical: 20, alignItems: 'center' } }); export default Home;
关键说明
- 解耦逻辑:独立的API模块专注于数据请求,组件专注于状态管理和UI渲染,代码更易维护、测试。
- 避免闭包问题:使用
setUsers(prevUsers => [...prevUsers, ...newUsers])函数式更新,确保获取最新的state值。 - 修复跳转不刷新:通过监听
focus事件,页面重新获得焦点时重置数据并加载第一页,解决返回后FlatList无更新的问题。 - 防止重复请求:在加载更多时判断
isLoading状态,避免同一时间多次触发网络请求。
内容的提问来源于stack exchange,提问作者user204069
相关产品推荐
相关产品推荐

