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

React Native应用为何反复发起网络请求?

React Native页面反复发起数百次请求问题解决

问题描述

目前仅在Android端测试,从服务器获取JSON数据以卡片形式展示,数据能正常显示,但应用会反复向服务器发起数百次请求。该页面通过导航栈与其他页面关联,登录页请求正常,仅此页面存在问题。

问题页面代码:

function WorkOrders({ navigation }) {
  const [data, setData] = useState("")
  fetch(`https://www.example.com/workorder?user=${global.email}`, {
              method: 'POST',
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
              }
  })
  .then((response) => response.json())
  .then((response) => {
    setData(response)
  })
  if(!!data["id"]){
    return (
      <ScrollView>
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Work Orders assigned to me</Text>
        <Card>
        <Card.Title>Work Order #{data["id"]}</Card.Title>
            <Card.Divider/>
            <Text>Creation date: {data["creationDate"]}</Text>
            <Text>Due Date: {data["dueDate"]}</Text>
            <Card.Divider/>
            <Text>Work Location: {data["workLocation"]}</Text>
            <Card.Divider/>
            <Text>Description: {data["workDetails"]}</Text>
        </Card>
      </View>
      </ScrollView>
    );
  } else {
    return(
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>You don't have any assigned work orders.</Text>
    </View>
    );
  }
}

问题分析

核心问题是**fetch请求直接放在组件顶层代码中**:React组件每次渲染(初始渲染、state更新后、父组件触发重渲染等)都会执行顶层代码。当setData(response)更新state时,组件会重新渲染,再次执行fetch,再次更新state,形成无限循环,导致大量重复请求。

另外,data初始化为空字符串"",后续转为对象,判断data["id"]时存在类型逻辑隐患。

修复方案

1. 使用useEffect包裹请求逻辑

useEffect可以控制副作用(如网络请求)的执行时机,避免每次渲染重复执行。空依赖数组[]确保请求仅在组件挂载时执行一次。

2. 初始化合理的state类型

将data初始化为空对象{},匹配后续返回的JSON数据类型,避免类型判断错误。

3. 添加错误处理

网络请求可能失败,通过try/catch捕获错误,避免应用崩溃。

修复后的代码:

import { useEffect, useState } from 'react';
import { ScrollView, View, Text } from 'react-native';
// 确保Card组件已正确导入

function WorkOrders({ navigation }) {
  // 初始化data为空对象,匹配后续数据类型
  const [data, setData] = useState({});

  useEffect(() => {
    const fetchWorkOrders = async () => {
      try {
        const response = await fetch(`https://www.example.com/workorder?user=${global.email}`, {
          method: 'POST',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        });
        const responseData = await response.json();
        setData(responseData);
      } catch (error) {
        console.error('工单数据请求失败:', error);
        // 可在此添加用户可见的错误提示,比如设置error state
      }
    };

    fetchWorkOrders();
  }, []); // 空依赖数组:仅组件挂载时执行一次

  // 简化id判断逻辑
  if (data.id) {
    return (
      <ScrollView>
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <Text>Work Orders assigned to me</Text>
          <Card>
            <Card.Title>Work Order #{data.id}</Card.Title>
            <Card.Divider />
            <Text>Creation date: {data.creationDate}</Text>
            <Text>Due Date: {data.dueDate}</Text>
            <Card.Divider />
            <Text>Work Location: {data.workLocation}</Text>
            <Card.Divider />
            <Text>Description: {data.workDetails}</Text>
          </Card>
        </View>
      </ScrollView>
    );
  } else {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>You don't have any assigned work orders.</Text>
      </View>
    );
  }
}

额外提示

  • 如果需要根据变量(如用户切换)重新请求,可将变量加入useEffect的依赖数组,例如[global.email],但需确保变量引用稳定(可变值可结合useRef处理)。
  • async/await相比链式then更易读,推荐用于异步逻辑编写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:40:20