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

React Native中Fetch API请求结果不一致问题排查

Expo Go中Fetch API首次请求异常,热重载后恢复的问题排查与解决

问题描述

使用Expo Go测试React Native应用时,通过Fetch API抓取https://www.thesubath.com/whats-on/的HTML内容,首次加载出现异常:返回结果要么是带循环引用的对象{"next": null, "parent": {"children": [[Circular]], "endIndex": null, "next": null, "parent": null, "prev": null, "startIndex": null, "type": "root"}},要么是空对象{}。但按下Ctrl+S触发热重载后,就能正常获取完整的HTML数据。

原代码

import React, { useEffect, useState } from 'react'
import { ActivityIndicator, StyleSheet, Text, useWindowDimensions, View } from 'react-native';


const EventsScreen = () => {
    const [eventsHTML, setEventsHTML] = useState({});
    const {width} = useWindowDimensions();

    const ParseEventsHTML = ()=>{
        console.log(eventsHTML);
    
    }

    
    const RefreshEvents = ()=>{
        console.log("refreshing events");
            fetch('https://www.thesubath.com/whats-on/')
            .then(response => response.text())
            .then(textResponse => {
                setEventsHTML(textResponse);
                ParseEventsHTML();

            });
        }

    useEffect(()=>{
        RefreshEvents();
        }, []);
  return (
    <View>
        {!eventsHTML? <ActivityIndicator/> : <Text>Hello world</Text>}
    </View>
  
  )
}
export default EventsScreen;

依赖配置(package.json)

{
  "name": "bathe",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@react-navigation/bottom-tabs": "^6.5.3",
    "@react-navigation/drawer": "^6.5.7",
    "@react-navigation/native": "^6.1.2",
    "@react-navigation/native-stack": "^6.9.8",
    "@reduxjs/toolkit": "^1.9.2",
    "cheerio": "^1.0.0-rc.12",
    "expo": "~47.0.12",
    "expo-status-bar": "~1.4.2",
    "firebase": "^9.16.0",
    "htmlparser2": "^8.0.1",
    "nativewind": "^2.0.11",
    "react": "18.1.0",
    "react-native": "0.70.5",
    "react-native-gesture-handler": "~2.8.0",
    "react-native-html-parser": "^0.1.0",
    "react-native-reanimated": "~2.12.0",
    "react-native-render-html": "^6.3.4",
    "react-native-safe-area-context": "4.4.1",
    "react-native-screens": "~3.18.0",
    "react-redux": "^8.0.5"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9"
  },
  "private": true
}

问题原因分析

  1. 状态类型不匹配:eventsHTML初始值设为对象{},但后续存储的是字符串类型的HTML,类型不一致导致React DevTools对状态解析异常,出现循环引用的错误输出。
  2. 异步状态更新的时序问题:setEventsHTML是异步操作,调用后立即执行ParseEventsHTML,此时读取的仍是旧状态值,而非刚更新的HTML内容。
  3. Expo Go初始加载的缓存/时序问题:首次启动时可能存在网络请求缓存或JS bundle加载时序异常,热重载后环境状态重置,请求恢复正常。

解决方案

1. 修正初始状态类型

将useState({})改为useState(''),确保状态类型与后续存储的HTML字符串一致。

2. 监听状态变化执行解析

通过useEffect监听eventsHTML的变化,确保只有状态更新完成且有内容时,才执行解析逻辑,避免读取旧值。

3. 添加请求错误处理

给Fetch请求添加错误捕获,避免请求失败时状态无更新,导致界面一直停留在加载状态。

修改后的代码

import React, { useEffect, useState } from 'react'
import { ActivityIndicator, StyleSheet, Text, useWindowDimensions, View } from 'react-native';

const EventsScreen = () => {
    // 初始状态改为空字符串,匹配HTML内容类型
    const [eventsHTML, setEventsHTML] = useState('');
    const { width } = useWindowDimensions();

    const ParseEventsHTML = () => {
        console.log(eventsHTML);
        // 这里可添加cheerio等HTML解析逻辑
    };

    const RefreshEvents = () => {
        console.log("refreshing events");
        fetch('https://www.thesubath.com/whats-on/')
            .then(response => {
                // 检查响应状态是否正常
                if (!response.ok) {
                    throw new Error(`请求失败:${response.status}`);
                }
                return response.text();
            })
            .then(textResponse => {
                setEventsHTML(textResponse);
            })
            .catch(error => {
                console.error('请求错误:', error);
                // 可在此添加错误提示逻辑
            });
    };

    useEffect(() => {
        RefreshEvents();
    }, []);

    // 监听状态变化,确保读取最新值
    useEffect(() => {
        if (eventsHTML) {
            ParseEventsHTML();
        }
    }, [eventsHTML]);

    return (
        <View>
            {!eventsHTML ? <ActivityIndicator /> : <Text>已获取HTML内容</Text>}
        </View>
    )
};

export default EventsScreen;

额外排查建议

如果问题仍存在,可尝试:

  • 在Expo Go设置中选择「Clear Cache」清除缓存;
  • 重启Expo开发服务;
  • 检查目标网站是否有反爬机制,可添加请求头模拟浏览器请求(比如headers: {'User-Agent': 'Mozilla/5.0'})。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:56:52