Next.js 13.4.3点击按钮后fetch请求无限循环问题求助
问题根源
你的代码存在两个核心问题导致fetch无限循环:
- 把
async直接标记在React组件函数上,同时在组件顶层直接执行await fetch——React组件函数本身不能是异步函数(即使Next.js客户端组件允许,这种写法也会导致每次渲染都重新执行异步逻辑)。 - 点击按钮调用
setShowModal(true)会触发组件状态更新,进而引发组件重渲染;每次重渲染时,组件顶层的fetch都会被重新执行,形成无限循环。
修复方案
方案一:用useEffect包裹异步请求(最直接修复)
将fetch逻辑放到useEffect中,通过依赖数组控制执行时机,确保只在组件挂载时执行一次:
"use client"; import { useState, useEffect } from "react"; export default function Home() { const [showModal, setShowModal] = useState(false); const [products, setProducts] = useState([]); useEffect(() => { const fetchProducts = async () => { const res = await fetch(`http://localhost:3000/products`, { cache: "no-store", }); const data = await res.json(); setProducts(data); }; fetchProducts(); }, []); // 空依赖数组:仅组件挂载时执行一次 return ( <> <button className="bg-pink-500 text-white active:bg-pink-600 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button" onClick={() => setShowModal(true)} > Open regular modal </button> {/* 模态框代码... */} </> ); }
方案二:使用数据获取库(推荐复杂场景)
如果项目需要频繁处理数据获取、缓存或重新获取逻辑,建议用SWR或React Query这类专门的库,它们能自动避免重复请求:
"use client"; import { useState } from "react"; import useSWR from "swr"; const fetcher = async (url: string) => { const res = await fetch(url, { cache: "no-store" }); return res.json(); }; export default function Home() { const [showModal, setShowModal] = useState(false); const { data: products } = useSWR(`http://localhost:3000/products`, fetcher); return ( <> <button className="bg-pink-500 text-white active:bg-pink-600 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" type="button" onClick={() => setShowModal(true)} > Open regular modal </button> {/* 模态框代码... */} </> ); }
关键提醒
- 永远不要在React组件函数体的顶层直接执行异步请求,否则每次组件重渲染都会重复发起请求。
- Next.js客户端组件中,
async/await仅适用于特定场景(比如Server Components),客户端组件的异步逻辑必须通过useEffect或数据获取库管理。
内容的提问来源于stack exchange,提问作者Captai-N
相关产品推荐
相关产品推荐

