Node.js+React注册表单报错及前端跳转问题求助
注册表单对接问题排查与修复
问题1:后端「Cannot set headers after they are sent to the client」错误
问题原因
后端代码中多次调用res.send():一开始就执行res.send(results),后续又在if分支里重复调用res.send()。HTTP响应只能发送一次,多次调用会触发这个错误,导致前端收到异常响应,出现Axios的ERR_NETWORK错误。同时插入数据的SQL未处理回调,无法感知插入是否成功。
修复后后端代码
const cors = require("cors"); const express = require("express"); const app = express(); const mysql = require("mysql"); app.use(cors()); app.use(express.json()); const db = mysql.createConnection({ host: "localhost", user: "root", password: "password", database: "ggsklogin", }); app.post("/checkusersk", (req, res) => { const username = req.body.username; const password = req.body.password; db.query("select username from skcred where username=?;", [username], (err, results) => { // 优先处理数据库查询错误 if (err) { return res.send({ err: err.message }); } // 用户名已存在 if (results.length > 0) { return res.send({ message: "username exists" }); } // 用户名不存在,执行插入并处理结果 db.query("insert into skcred(username,password) values(?,?)", [username, password], (insertErr) => { if (insertErr) { return res.send({ err: insertErr.message }); } res.send({ message: "done" }); }); }); });
修复说明
- 移除多余的
res.send(results),确保每个分支只发送一次响应 - 使用
return终止后续代码执行,避免进入其他分支 - 给插入SQL添加回调函数,处理插入失败的情况并返回错误信息
问题2:前端验证通过后无法跳转至/sk-details
问题原因
- 密码校验逻辑错误:
passwordcheck函数中,无论密码是否匹配都会调用check(),导致不匹配时也会发起请求 - 响应判断错误:
if(response.data=0)是赋值操作而非比较,逻辑完全错误 - 跳转时机错误:组件顶层的
if(loginstatus=='done')会在每次渲染时执行,可能触发无限跳转,且时机不合理
修复后前端代码
import React, { useState } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; function Newlogin() { const navigate = useNavigate() const [usernamea, setusername] = useState('') const [passworda, setpassword] = useState('') const [repeatpass, setreapeatpass] = useState('') const [loginstatus, setLoginstatus] = useState('') const check = () => { axios.post('http://localhost:3001/checkusersk', { username: usernamea, password: passworda, }).then((response) => { if (response.data.err) { setLoginstatus('注册失败:' + response.data.err); return; } setLoginstatus(response.data.message); // 注册成功时跳转 if (response.data.message === 'done') { navigate('/sk-details') } }).catch(() => { setLoginstatus('网络请求失败,请稍后重试'); }) } const passwordcheck = (e) => { e.preventDefault(); if (passworda !== repeatpass) { setLoginstatus("password mismatch") return; // 密码不匹配时终止流程,不发起请求 } check() } return ( <div> <div> <input type="text" placeholder='enter username' name='username' onChange={(e) => setusername(e.target.value)} /> <br /> <br /> <input type="password" placeholder='enter password' name='password' onChange={(e) => setpassword(e.target.value)} /> <br /> <br /> <input type="password" placeholder='repeat password' name='repeatpass' onChange={(e) => setreapeatpass(e.target.value)} /> <br /> <br /> <button onClick={passwordcheck}>注册</button> </div> <div className="alert alert-info" role="alert"> {loginstatus} </div> </div> ); } export default Newlogin;
修复说明
- 修正
passwordcheck函数:密码不匹配时直接返回,不调用check() - 修正响应判断逻辑:通过
response.data.message === 'done'判断注册成功后跳转 - 移除组件顶层的跳转逻辑,改为在请求成功回调中处理跳转,避免无效渲染触发跳转
- 添加
catch捕获网络请求错误,给用户明确提示 - 修正重复密码输入框的
text属性为type="password",确保密码隐藏 - 给按钮添加文本“注册”,提升用户体验
- 用
className替代class,符合React语法规范
内容的提问来源于stack exchange,提问作者DHARSHINI S
相关产品推荐
相关产品推荐

