You need to enable JavaScript to run this app. React useEffect Hook首次加载后偶发不调用API、状态未设置报错问题
优惠活动
大模型
产品
解决方案
定价
更多

React useEffect Hook首次加载后偶发不调用API、状态未设置报错问题

报错原因

你的报错本质不是useEffect没有调用API,是组件首次渲染时data初始值为null,你在<img>标签的src属性中直接访问data.volumeInfo,没有做非空判断,导致API请求还没返回结果,组件就因为空值访问直接渲染崩溃,所以看起来像是API没调用成功。

另外还有几个隐性问题:

  • 异步逻辑写法错误:你声明了async函数但没有搭配await使用,try/catch完全无法捕获fetch的请求报错
  • HTML结构不规范:重复嵌套了多个<body>标签,可能引发额外的渲染异常
完整修复代码
import '../App.css';
import Navigation from './Navigation';
import React, { useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';

const Milestone1 = () => {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        const callAPI = async () => {
            try {
                const res = await fetch("https://www.googleapis.com/books/v1/volumes/Wfan6L9RGgYC");
                const result = await res.json();
                setData(result);
                setLoading(false);
            } catch (e) {
                console.log(e);
                setError(e);
                setLoading(false);
            }
        };
        callAPI();
    }, []);

    // 加载中展示提示
    if (loading) return <div>加载中...</div>;
    // 请求出错展示报错
    if (error) return <div>请求失败,请刷新重试</div>;
    // 无数据时展示空提示
    if (!data) return <div>暂无数据</div>;

    return (
        <div className="school">
            <header className="App-header">
            </header>
            <center>
                <div className="navigation">
                    <Navigation />
                </div>
                <div className="App-body">
                    <h2>Milestone 1</h2>
                    <h5>Title: {data.volumeInfo?.title}</h5>
                    {data.volumeInfo?.imageLinks?.smallThumbnail && (
                        <img src={data.volumeInfo.imageLinks.smallThumbnail} alt="书籍封面" />
                    )}
                    <h5>
                        Authors: {data.volumeInfo?.authors} 
                        Publish info: {data.volumeInfo?.publisher} {data.volumeInfo?.publishedDate} 
                        Country: {data.saleInfo?.country}
                    </h5>
                    <h5>Rating: {data.volumeInfo?.averageRating}</h5>
                    <NavLink to="/Milestone1part2">Milestone 1 part two</NavLink><br/>
                </div>
            </center>
        </div>
    );
}

export default Milestone1;
核心修改点说明
  1. 修正异步逻辑:用async/await搭配try/catch正确捕获请求异常,新增加载状态、错误状态处理,避免请求过程中渲染空数据
  2. 增加非空判断:所有深层属性访问都用可选链?.做判空,图片渲染前先判断资源地址是否存在,避免空值报错
  3. 修正HTML结构:删掉重复嵌套的<body>标签,用普通div包裹内容,符合HTML规范
  4. 新增前置渲染拦截:加载完成、请求成功前不渲染业务内容,从根源避免空值访问问题
简化版Hook逻辑
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
    const fetchData = async () => {
        const res = await fetch("https://www.googleapis.com/books/v1/volumes/Wfan6L9RGgYC");
        const result = await res.json();
        setData(result);
        setLoading(false);
    };
    fetchData();
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 17:24:11