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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:45:10