Next.js+Laravel Sanctum项目API重复请求问题求助
解决Next.js客户端组件重复发送API请求的问题
问题原因
你直接在组件函数顶层调用了fetchPost(),组件每次渲染时都会执行这个函数,而setPost、setTitle等状态更新操作又会触发组件重新渲染,形成无限渲染循环,导致API请求被重复发送。
解决方法
使用React的useEffect钩子包裹数据获取逻辑,控制请求仅在组件挂载或指定依赖项变化时执行:
- 导入
useEffect - 将
fetchPost()放入useEffect中,设置依赖项为params.id(仅当post ID变化时重新请求) - 合并重复的
usePosts调用,避免多次初始化hook
修改后的完整代码
'use client' import { usePosts } from "@/hooks/post" import { useState, useEffect } from "react" // 新增useEffect导入 import InputError from "@/components/InputError"; import styles from "../page.module.css"; const PostEditForm = ({params}) => { // 合并usePosts的解构,避免重复调用 const { getPost, updatePost } = usePosts(); const [post, setPost] = useState(null); const [title, setTitle] = useState('') const [body, setBody] = useState('') const [errors, setErrors] = useState([]) const [isLoading, setIsLoading] = useState(true) // 可选:添加加载状态 const [fetchError, setFetchError] = useState(null) // 可选:添加错误状态 const fetchPost = async () => { setIsLoading(true) setFetchError(null) try{ const postData = await getPost(params.id) setPost(postData) setTitle(postData.title) setBody(postData.body) }catch(error){ setFetchError(error.message || '获取文章失败') console.error('获取文章出错:', error) } finally { setIsLoading(false) } } // 使用useEffect包裹,仅在params.id变化时执行 useEffect(() => { fetchPost() }, [params.id, getPost]) // 依赖项包含params.id和getPost,避免闭包问题 const submitForm = async event => { event.preventDefault() await updatePost(params.id,{ title, body, setErrors }) } // 可选:根据加载状态渲染不同内容 if(isLoading) return <div className={styles.loading}>加载中...</div> if(fetchError) return <div className={styles.error}>{fetchError}</div> if(!post) return <div className={styles.error}>文章不存在</div> return ( <form onSubmit={submitForm} className={styles.form}> <div> <label>标题</label> <input type="text" value={title} onChange={(e) => setTitle(e.target.value)} /> {errors.title && <InputError message={errors.title} />} </div> <div> <label>内容</label> <textarea value={body} onChange={(e) => setBody(e.target.value)} /> {errors.body && <InputError message={errors.body} />} </div> <button type="submit">更新文章</button> </form> ) } export default PostEditForm
额外说明
- 依赖项数组
[params.id, getPost]:确保当文章ID变化时重新请求,同时如果getPost函数有变化(比如hook内部逻辑更新)也会重新执行,避免闭包问题。 - 添加加载和错误状态:提升用户体验,避免页面出现异常内容。
- 错误处理:不再忽略catch块,方便排查问题和给用户反馈。
内容的提问来源于stack exchange,提问作者Calma Muzik
相关产品推荐
相关产品推荐

