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

React 18 useEffect搭配axios请求触发无限循环问题求助

React 18 调用TMDB接口setState触发无限循环问题修复

问题根因

无限循环的核心触发点是useEffect依赖数组配置逻辑错误,形成了闭环触发链:

  • 组件首次渲染时,绑定在useEffect里的接口请求逻辑执行,请求成功后调用setMovieList更新movieList状态
  • 你在负责拉取电影列表的useEffect依赖数组中加入了movieList,状态更新触发组件重渲染时,React检测到依赖项变化,会重新执行effect内的全部逻辑
  • effect重新执行后再次发起接口请求、再次调用setMovieList更新状态,整个流程无限循环,最终表现为请求不停发、控制台无限打印返回结果

另外代码里还存在几个不影响循环但会导致异常的小问题:

  • 异步写法混用async/await和.then链,逻辑冗余且容易出错
  • TMDB接口的page参数写为1p属于笔误,正确参数应为page=1
  • setMovieList之后立刻执行console.log(movieList)无法拿到最新状态值,React的setState是异步批处理机制,更新后的值要到下一次渲染周期才能获取到

修复方案

  • 调整拉取列表的useEffect依赖:首次挂载拉取一次全量列表的场景下,依赖数组设为空数组[],表示仅在组件挂载时执行一次effect,从根源切断循环触发链
  • 统一异步请求写法,修正接口参数笔误,增加请求错误捕获逻辑
  • 如果需要查看更新后的movieList值,单独加一个依赖movieList的effect专门打印日志,不要在更新状态的同一步骤同步打印

修复后完整代码

import { useEffect, useState } from "react"
import { useNavigate } from "react-router-dom"
import axios from 'axios'


function Listado() {

    const [movieList, setMovieList] = useState([])

    const navigate = useNavigate()

    // 登录鉴权逻辑
    useEffect(() => {
        const token = localStorage.getItem('token')
        console.log(token)
        if (token == null) {
            navigate('/')
        }
    }, [navigate])

   
    // 首次挂载拉取电影列表
    useEffect(() => {
        const apiKey = 'b34999ac538aed71a19355d996f1081f'
        const fetchMovieList = async () => {
            try {
                const response = await axios.get(`https://api.themoviedb.org/3/discover/movie`, {
                    params: {
                        api_key: apiKey,
                        language: 'es-ES',
                        page: 1
                    }
                })
                setMovieList(response.data.results)
            } catch (err) {
                console.error('拉取电影列表失败:', err)
            }
        }

        fetchMovieList()

    }, []) // 空数组表示仅挂载时执行一次

    // 单独监听movieList变化打印最新值
    useEffect(() => {
        console.log('最新电影列表:', movieList)
    }, [movieList])
   

    return (
        <>
            {/* 列表渲染逻辑 */}
            <div className='col3' style={{ border: '1px solid red' }}>Peli 1</div>
        </>)
}
export default Listado

补充说明:如果后续需要做分页、关键词搜索等触发重新拉取列表的功能,只需要把页码、搜索关键词这类触发请求变化的变量加入拉取列表的useEffect依赖数组即可,永远不要把当前effect内会更新的状态直接加入依赖(除非加了新旧值对比的判断,值完全相等时不执行setState)

内容的提问来源于stack exchange,提问作者Jose Antonio Miro Erdmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 06:03:12