Next.js中react-query的useMutation异常及通知问题排查
Next.js + react-query POST请求问题排查与修复
问题现象
- 提交表单后新用户已成功存入MongoDB,但终端控制台提示:
API resolved without sending a response for /api/users, this may result in stalled requests. - 当添加名称重复的用户时,
useMutation的onError回调未触发,始终执行onSuccess逻辑,不符合预期
相关代码片段
1. AddingForm组件代码
/*** components ***/ import {Button, InputGroup} from "../index"; import {useMutation} from "react-query"; import {addUser} from "../../../utils/helpers/helper"; /*** form validation ***/ import {useFormik} from "formik"; import {validateInput} from "../../../utils/functions/validateInput"; const AddingForm = () => { const { mutate, status } = useMutation(addUser, { onSuccess: data => { console.log(data); const message = "success" alert(message) }, onError: () => { alert("there was an error") }, /*onSettled: () => { queryClient.invalidateQueries('create'); }*/ }); const newUser = () => { mutate(formik.values) } const formik = useFormik({ initialValues: { name: "", email: "" }, onSubmit: newUser, validate: validateInput }); return ( <> <form onSubmit={formik.handleSubmit}> <InputGroup label="Name" name="name" error={formik.errors.name} isTouched={formik.touched.name} {...formik.getFieldProps("name")} /> <InputGroup label="Email" name="email" error={formik.errors.email} isTouched={formik.touched.email} {...formik.getFieldProps("email")} /> <Button disabled={!formik.values.name && !formik.values.email} className={`w-full ${!formik.values.name || !formik.values.email ? 'bg-gray-200 text-gray-500' : 'bg-orange-200'}`} type="submit" > Aggiungi </Button> </form> </> ) } export default AddingForm;
2. addUser工具函数
/*** POST new user ***/ export const addUser = async (formData) => { try { const { response } = await axios.post(`${BASE_URL}/api/users`, formData); return response.data; } catch (error) { console.log("ERROR FROM TRY/CATCH", error.message) return error.message } }
3. API路由处理函数(pages/api/users)
import connectDB from "../../../db/connectDB"; import {getUsers, postUser, updateUser, deleteUser} from "../../../db/controllers/AddedUserController"; /** * @param {import('next').NextApiRequest} req * @param {import('next').NextApiResponse} res */ export default async function handler(req, res) { await connectDB().catch(() => res.status(405).json({error: "Connection Error"})) const {method} = req switch(method) { case "GET": await getUsers(req, res) break; case "POST": await postUser(req, res) break; case "PUT": await updateUser(req, res) break; case "DELETE": await deleteUser(req, res) break; default: res.setHeader("Allow", ["GET", "POST", "PUT", "DELETE"]) res.status(405).end(`Method ${method} not allowed`) } }
4. postUser控制器函数
/*** POST http://localhost:3000/api/users ***/ export async function postUser(req, res) { try { console.log("FORM DATA", req.body) if(!req.body || req.body === undefined) return res.status(404).json({error: "Form data not provided"}) await AddedUser.create(req.body); } catch(error) { res.status(404).json({error: error.message}) } }
问题原因分析
- 终端响应警告:
postUser函数中,用户创建成功的分支没有返回任何响应,Next.js无法确认请求已完成,因此抛出"未发送响应"的警告。 - useMutation onError不触发:
addUser函数捕获错误后直接返回错误信息,而非抛出异常。react-query的useMutation仅在内部函数抛出异常时才会触发onError,返回错误值会被视为成功结果。
修复方案
1. 修复postUser控制器,确保所有分支返回响应
在用户创建成功时返回201状态码和用户数据,同时调整错误状态码更符合语义:
export async function postUser(req, res) { try { console.log("FORM DATA", req.body) if(!req.body || req.body === undefined) { return res.status(400).json({error: "Form data not provided"}) } const newUser = await AddedUser.create(req.body); // 创建成功返回201状态和用户数据 res.status(201).json(newUser); } catch(error) { // 重复键等数据库冲突返回409状态 res.status(409).json({error: error.message}) } }
2. 修改addUser函数,抛出异常而非返回错误
让react-query能够捕获到错误,从而触发onError回调:
export const addUser = async (formData) => { try { // 修正axios解构错误:axios.post直接返回响应对象 const response = await axios.post(`${BASE_URL}/api/users`, formData); return response.data; } catch (error) { console.log("ERROR FROM TRY/CATCH", error.message) // 抛出错误,让useMutation捕获 throw new Error(error.response?.data?.error || error.message); } }
3. 优化useMutation错误处理(可选)
可以在onError中获取具体错误信息,提升用户体验:
const { mutate, status } = useMutation(addUser, { onSuccess: data => { console.log(data); alert("用户添加成功") }, onError: (error) => { alert(`添加失败:${error.message}`) }, // 如果需要添加后刷新用户列表,取消注释并传入queryClient // onSettled: () => { // queryClient.invalidateQueries('users'); // } });
额外注意
- 确保
AddedUser模型中已给name字段添加唯一约束,这样重复添加时MongoDB才会抛出错误。 - 原代码中axios的解构错误:
const { response } = await axios.post(...)是错误的,axios.post直接返回响应对象,应改为const response = await axios.post(...)。
内容的提问来源于stack exchange,提问作者D.D.
相关产品推荐
相关产品推荐

