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

React组件useState初始值为null时出现读取undefined属性报错求助

React项目中useState初始值为null导致的解构与API请求报错解决

问题描述

我正在借助Rapid API的Youtube V3 API制作YouTube克隆项目,用axios封装了fetchFromApi方法获取数据。当给useState Hook设置初始值为null时,出现两个核心报错:

  1. Cannot read properties of undefined (reading '0'):API请求返回结果时直接访问data.items[0],但data.items可能为空或未定义
  2. 解构videoDetail时无法读取snippet/statistics属性:组件首次渲染时videoDetail为null,直接解构会触发类型错误

相关代码:

import React, { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import ReactPlayer from 'react-player'
import { Typography, Box, Stack } from '@mui/material'
import { CheckCircle } from '@mui/icons-material'
import { Videos } from './'
import { fetchFromApi } from '../utils/fetchFromApi'

const VideoDetail = ({ channelDetail }) => {

const { id } = useParams();
const [videoDetail, setVideoDetail] = useState(null);

useEffect(() => {
fetchFromApi(`videos?part=snippet,statistics&id=${id}`)
  .then((data) => setVideoDetail(data.items[0]));
}, [id])

const { snippet: { title, channelId, channelTitle } , statistics: {
viewCount, likeCount } } = videoDetail;

return (
<Box minHeight='95vh'>
  <Stack direction={{ xs: 'column', md: 'row' }} >
    <Box flex={1}>
      <Box sx={{ width: '100%', position: 'sticky', top: '86px' }}>
        <ReactPlayer url={`https://www.youtube.com/watch?v=${id}`}
          controls
          className='react-player' />
        <Typography color='#fff' variant='h5' fontWeight='bold' p={2}>
          {title}
        </Typography>
        <Stack direction='row' justifyContent='space-between' py={1} px={2} sx={{ color: '#fff' }}>
        </Stack>
      </Box>
    </Box>
  </Stack>
</Box>
)
}

export default VideoDetail

解决方案

1. 修复API请求中的data.items[0]报错

在设置videoDetail之前,先判断data.items是否存在且包含元素,避免直接访问索引导致的未定义错误,同时添加错误捕获:

useEffect(() => {
  fetchFromApi(`videos?part=snippet,statistics&id=${id}`)
    .then((data) => {
      // 安全访问data.items,确保存在且有数据
      if (data?.items?.length > 0) {
        setVideoDetail(data.items[0]);
      } else {
        // 无数据时重置状态,可根据需求添加提示
        setVideoDetail(null);
      }
    })
    .catch(err => {
      // 捕获请求异常,防止页面崩溃
      console.error('视频详情获取失败:', err);
      setVideoDetail(null);
    });
}, [id])

2. 修复解构videoDetail时的类型错误

由于组件首次渲染时videoDetail为null,直接解构会报错,可通过两种方式解决:

方式一:使用可选链+默认值

给解构添加默认空对象,确保即使videoDetail为null也不会报错:

const { 
  snippet: { title = '', channelId = '', channelTitle = '' } = {}, 
  statistics: { viewCount = 0, likeCount = 0 } = {} 
} = videoDetail || {};

方式二:添加条件渲染

在videoDetail存在时再渲染相关内容,同时添加加载状态:

return (
  <Box minHeight='95vh'>
    {videoDetail ? (
      <Stack direction={{ xs: 'column', md: 'row' }} >
        <Box flex={1}>
          <Box sx={{ width: '100%', position: 'sticky', top: '86px' }}>
            <ReactPlayer 
              url={`https://www.youtube.com/watch?v=${id}`}
              controls
              className='react-player' 
            />
            <Typography color='#fff' variant='h5' fontWeight='bold' p={2}>
              {title}
            </Typography>
            <Stack direction='row' justifyContent='space-between' py={1} px={2} sx={{ color: '#fff' }}>
              <Typography>
                {channelTitle} <CheckCircle sx={{ fontSize: 12, color: 'gray', ml: 0.5 }} />
              </Typography>
              <Stack direction='row' gap='20px'>
                <Typography>{parseInt(viewCount).toLocaleString()} 次观看</Typography>
                <Typography>{parseInt(likeCount).toLocaleString()} 个赞</Typography>
              </Stack>
            </Stack>
          </Box>
        </Box>
      </Stack>
    ) : (
      // 加载状态提示
      <Box display='flex' justifyContent='center' alignItems='center' height='80vh'>
        <Typography color='#fff' variant='h6'>加载中...</Typography>
      </Box>
    )}
  </Box>
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:53:16