使用Axios、useState/useEffect的React函数组件无限重渲染问题求解
问题原因
你的代码存在三处核心问题,共同引发了报错:
useEffect回调直接使用await关键字但未标记为async,本身属于语法错误。即使要在useEffect中写异步逻辑,也不能直接将async函数作为useEffect的入参,需要在回调内部定义异步函数再执行。- 异步逻辑混乱:同时混用
await和.then()两种异步处理方式,还调用了未定义的getQuote()函数,运行时会直接抛出未定义错误。 - 触发无限重渲染的根因:你实际运行的代码中,请求数据+修改
quote1状态的逻辑没有被正确包裹在依赖为空数组的useEffect中,而是直接写在了组件函数体顶层,导致每次组件渲染都会发起请求、修改状态触发重新渲染,形成死循环。
修复后的完整代码
import React, { useEffect, useState } from 'react'; import { Row, Col, CardGroup } from 'reactstrap'; import axios from 'axios'; import QuoteCard from './QuoteCard'; // 按照API返回的实际字段定义数据类型,符合TS规范 interface Quote { _id: string; quoteText: string; quoteAuthor: string; quoteGenre: string; __v: number; } const MainQuotes = () => { // 给state声明类型,初始值设为null const [quote1, setQuote1] = useState<Quote | null>(null); useEffect(() => { // 内部定义异步请求函数 const fetchRandomQuote = async () => { try { const resp = await axios.get('https://quote-garden.herokuapp.com/api/v3/quotes/random'); setQuote1(resp.data.data[0]); } catch (err) { console.error('名言获取失败:', err); } }; // 执行请求 fetchRandomQuote(); }, []); // 依赖为空数组,仅在组件首次挂载时执行一次 // 增加加载状态,避免quote1为空时子组件接收异常props if (!quote1) return <div>加载中...</div>; return ( <Row> <Col> <CardGroup> <QuoteCard quoteData={quote1} /> </CardGroup> </Col> </Row> ); }; export default MainQuotes;
注意事项
- 不要在组件函数顶层直接调用会修改state的方法,所有初始化数据请求都需要放在依赖为空数组的
useEffect中,保证仅执行一次 - async/await 和 .then() 两种异步处理方式不要混用,统一使用一种即可
- TypeScript项目中需要给state、props声明明确的类型,避免隐式any类型报错
内容的提问来源于stack exchange,提问作者Jack_Lynch
相关产品推荐
相关产品推荐

