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

React JS如何捕获HTTP请求返回对象缺失指定数组的异常

问题修复方案

崩溃原因

页面崩溃的核心原因是未对接口可能缺失的字段做空值兜底:TMDB的watch/providers接口返回结构是动态的,当对应地区没有某类播放渠道时,返回的地区数据对象不会携带flatrate(订阅播放)、rent(租赁)字段,此时直接对undefined值调用数组的.map()方法会抛出JS运行时错误,中断React渲染流程导致整个页面崩溃。
原有代码还存在几个隐藏问题:

  • 请求错误捕获仅覆盖网络请求、JSON解析阶段,未覆盖接口返回字段缺失的场景
  • 列表项使用Math.random()作为key,每次重渲染都会生成新值,导致DOM重复创建、渲染异常
  • img标签的src属性存在语法错误,多写了多余的点号
  • 初始状态streamingData为null,字段读取时存在额外的空值风险
  • 混用async/await和.then()链式调用,错误捕获范围不全

具体修复逻辑

  • 初始化streamingData时就给好默认空结构,所有数组字段默认赋值为空数组,从根源避免读取undefined的问题
  • 接口返回后逐层判断字段是否存在,对数组类型做类型校验,不存在/类型不对时直接兜底为空数组
  • 改用接口返回的流媒体平台唯一标识provider_id作为列表key,保证渲染稳定性
  • 修正img标签语法,补充alt属性提升可访问性
  • 增加空状态提示,当某类渠道不存在时给用户明确反馈,避免空白区域
  • 用try/catch统一处理所有请求、解析、数据处理阶段的错误,出错时重置为空状态

修复后完整代码

import React, { useState } from 'react'
import classes from './Streaming.module.css'

const Streaming = (props) => {
  const [streamingOn, setStreamingOn] = useState(false)
  // 初始化时直接给默认空结构,避免初始null导致的读取错误
  const [streamingData, setStreamingData] = useState({
    flatrate: [],
    rent: [],
    link: ''
  })   
  
  async function receiveStreaming() {
    try {
      const res = await fetch(`https://api.themoviedb.org/3/movie/${props.movie}/watch/providers?api_key=35135143f12a5c114d5d09d17dfcea12`)
      const result = await res.json()
      // 兜底:US地区数据不存在时使用默认空结构
      const usRegionData = result?.results?.US || {
        flatrate: [],
        rent: [],
        link: ''
      }
      // 对每个字段做类型校验,非数组/不存在时兜底为空数组
      setStreamingData({
        flatrate: Array.isArray(usRegionData.flatrate) ? usRegionData.flatrate : [],
        rent: Array.isArray(usRegionData.rent) ? usRegionData.rent : [],
        link: usRegionData.link || ''
      })   
      setStreamingOn(true)
    } catch (error) {
      console.error("获取流媒体信息失败: ", error) 
      // 出错时重置为空状态,避免渲染报错
      setStreamingData({
        flatrate: [],
        rent: [],
        link: ''
      })
      setStreamingOn(false)
    }
  }

  const displayStreaming = (data) => {   
    const { flatrate: streamList, rent: rentList, link } = data
    // 用接口返回的唯一provider_id作为列表key,保证渲染稳定
    const streamItems = streamList.map(provider =>
      <li key={provider.provider_id}>    
        <a href={link}>
          <img 
            className={classes.logoimg} 
            src={`https://image.tmdb.org/t/p/w500/${provider.logo_path}`} 
            alt={provider.provider_name}
          />
        </a>
      </li>
    ) 
    const rentItems = rentList.map(provider =>
      <li key={provider.provider_id}>
        <a href={link}>
          <img 
            className={classes.logoimg} 
            src={`https://image.tmdb.org/t/p/w500/${provider.logo_path}`}
            alt={provider.provider_name}
          />
        </a>
      </li>
    )

    return (
      <>
        <p>订阅播放平台</p>
        {streamItems.length ? (
          <ul className={classes.logolist}>{streamItems}</ul>
        ) : (
          <p>当前地区暂无可用订阅播放渠道</p>
        )}
        <p>租赁平台</p>
        {rentItems.length ? (
          <ul className={classes.logolist}>{rentItems}</ul>
        ) : (
          <p>当前地区暂无可用租赁渠道</p>
        )}
      </>
    )
  }

  return (
    <>
      <button onClick={receiveStreaming}>查看播放渠道</button>
      <div className={classes.streaminglogos}>  
        {streamingOn && <div>{displayStreaming(streamingData)}</div> }
      </div>
    </>
  )
}

export default Streaming

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:15:29