Next.js+TS项目POST提交表单到/api/users无响应问题求助
最简解决指南
问题根因梳理
你现在碰到的问题是3个独立错误叠加导致的:
- 提交按钮上绑定的
preventDefault直接阻断了表单提交流程,你的onSubmit逻辑全程没触发 - 后端
/api/users接口没有区分请求方法,不管GET还是POST都只返回固定模拟数据,完全没处理POST请求的参数 - 你用
useState存储的用户数据只保存在当前组件内存中,页面刷新/组件重载就会自动重置
分步修改代码
1. 修改前端Form组件
直接用react-hook-form返回的表单数据,删掉冗余的DOM取值逻辑,移除按钮上的阻断提交代码:
import React, { useState, useEffect } from 'react'; import styles from '../styles/Home.module.css' import data from '../component/data.json' import { useForm } from 'react-hook-form' import axios from 'axios'; // 复用的axios实例 const api = axios.create({ baseURL: `http://localhost:3000/api/users` }) export default function Form(props:any) { const eng = props.eng const setReg = props.setReg // 存用户列表,从localStorage初始化避免刷新丢失 const [userDb, setUserDb] = useState(() => { const saved = localStorage.getItem('userDb') return saved ? JSON.parse(saved) : [] }) const { register, handleSubmit } = useForm(); // 组件加载时拉取用户数据 useEffect(() => { api.get('/').then(res => { console.log("API.GET DATA:", res.data) }) }, []) // 提交逻辑直接用react-hook-form返回的data,不用自己读DOM async function onSubmit(data: any) { try { // 发POST请求 const postRes = await api.post('/', { id: Date.now().toString(), ...data }) console.log("POST返回结果:", postRes.data) // 把新用户加到本地列表并存localStorage避免刷新丢失 const newUserList = [...userDb, postRes.data] setUserDb(newUserList) localStorage.setItem('userDb', JSON.stringify(newUserList)) // 提交成功再执行setReg setReg(true) } catch (e) { console.error("提交失败:", e) } } return ( <div className={styles.container}> <main className={styles.mainForm}> <h1 className={styles.titleForm}> {eng ? data.eng.welcome : data.fr.welcome} </h1> {/* 表单绑定提交逻辑 */} <form onSubmit={handleSubmit(onSubmit)} className={styles.form}> <div> <p className={styles.descriptionForm}>{eng ? data.eng.form : data.fr.form}</p> <label><b className={styles.description}>{eng ? data.eng.user : data.fr.user}</b></label> <input type="text" placeholder={eng ? data.eng.enterUser : data.fr.enterUser} {...register('username', {required: true})} /> <label><b className={styles.description}>{eng ? data.eng.email : data.fr.email}</b></label> <input type="email" placeholder={eng ? data.eng.enterEmail : data.fr.enterEmail} {...register('email', {required: true})} /> <label><b className={styles.description}>{eng ? data.eng.password : data.fr.password}</b></label> <input type="password" placeholder={eng ? data.eng.enterPassword : data.fr.enterPassword} {...register('password', {required: true})} /> {/* 删掉原来的onClick阻断逻辑,type=submit会自动触发表单提交 */} <button type="submit" className={styles.registerbtn}> <h1>{eng ? data.eng.save : data.fr.save}</h1> </button> </div> </form> </main> </div> ) }
2. 修改/pages/api/users.ts接口
区分请求方法,POST请求读取前端传的参数返回:
import type { NextApiRequest, NextApiResponse } from 'next' type User = { id: string, username: string, email: string, password: string } // 临时内存存储用户数据,重启服务会清空,生产环境可以换成数据库/json文件存储 let userList: User[] = [ { id: "user1", username: "señorJuan", email: "C1@mail.com", password: "password" } ] export default function handler( req: NextApiRequest, res: NextApiResponse<User | User[]> ) { // 区分请求方法 if (req.method === 'GET') { // GET请求返回所有用户 res.status(200).json(userList) } else if (req.method === 'POST') { // POST请求读取body里的用户数据,加入列表返回 const newUser = req.body as User userList.push(newUser) res.status(201).json(newUser) } else { res.status(405).end('不支持的请求方法') } }
关于本地数据重置的说明
你之前存的数据刷新就没,是因为存在组件的useState里,属于页面内存数据,刷新就会释放。上面的代码里用了两个方案解决:
- 前端用
localStorage持久化存储,只要用户不清浏览器缓存就不会丢失 - 后端用数组存储(重启服务会清空,如果要永久存可以把userList写到本地json文件里,每次读写操作都更新json文件即可)
内容的提问来源于stack exchange,提问作者Ariel Flores
相关产品推荐
相关产品推荐

