You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React登录组件需三次点击才跳转问题(Node.js+Express+MySQL)

登录系统前两次点击失败、第三次才跳转的问题修复方案

核心问题分析

  1. 前端请求时序错误:POST请求还未完成后端验证,就提前触发GET请求获取状态,导致拿到的是旧状态。
  2. React状态更新特性误用:刚调用setAuth就用auth变量判断,此时auth还是更新前的旧值。
  3. 后端全局变量设计错误:用全局auth存储验证状态,多请求下状态会混乱,且POST请求未直接返回验证结果,依赖后续GET请求的逻辑完全不合理。
  4. 数据库查询结果判断错误:用result != null判断是否匹配用户,实际上无匹配时result是空数组而非null。

前端Signin.js修改方案

import React, { useState } from 'react';
import Navbar from './Navbar';
import './signin.css';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';

function Signin() {
    const [userId, setUserId] = useState("");
    const [password, setPassword] = useState("");
    const [accessCode, setAccessCode] = useState("");
    const navigate = useNavigate();

    const signInInfoSent = async () => {
        try {
            const response = await axios.post("http://localhost:3001/api/get/signin", {
                userId: userId,
                password: password
            });

            if (response.data.success) {
                navigate("/Dashhome");
            } else {
                alert('Incorrect Login/Password');
            }
        } catch (error) {
            console.error("登录请求失败:", error);
            alert('登录请求出错,请稍后重试');
        }
    };

    return (
        <>
            <Navbar />
            <div id="signUp">
                <div id="form">
                    <label htmlFor="userId">User ID</label>
                    <input
                        type="text"
                        id="userId"
                        placeholder="Username"
                        onChange={(e) => setUserId(e.target.value)}
                    />

                    <label htmlFor="password">Password</label>
                    <input
                        type="password"
                        id="password"
                        placeholder="Password"
                        onChange={(e) => setPassword(e.target.value)}
                    />

                    <label htmlFor="otp">Access Code</label>
                    <input
                        type="text"
                        id="otp"
                        placeholder="OTP"
                        onChange={(e) => setAccessCode(e.target.value)}
                    />

                    <button onClick={signInInfoSent}>Sign in</button>
                </div>
            </div>
        </>
    );
}

export default Signin;

前端修改说明

  • 移除多余的receiveauthentication函数,直接在POST请求响应中处理登录结果,解决时序问题。
  • 改用useNavigate进行路由跳转,替代原生document.location.href,符合React Router规范。
  • 用async/await处理异步请求,代码更清晰,同时增加错误捕获逻辑。
  • 修正输入框type属性为标准的text(原textbox非HTML标准类型)。

后端index.js修改方案

const express = require('express')
const app = express()
const mySql = require('mysql');
const cors = require('cors')
const bodyParser = require('body-parser')

const db = mySql.createPool({
    host:"127.0.0.1",
    user:"root",
    password:"password",
    database:"kotekdatabase"
})

app.use(bodyParser.urlencoded({extended: true}))
app.use(express.json())
app.use(cors())

let userIdG;
var trade_data = {};

app.post("/api/get/signin", (req,res)=>{
    const userid = req.body.userId;
    userIdG = userid;
    const password = req.body.password;
    const sqlSelect = `SELECT * FROM signup WHERE userid = ? AND password = ?`;
    
    db.query(sqlSelect,[userid , password], (err, result)=> {
        if(err){
            console.error("数据库查询错误:", err);
            return res.status(500).json({success: false, message: "服务器内部错误"});
        }
        if(result.length > 0)
        {
            console.log("登录成功:", userid);
            res.json({success: true});
        }
        else
        {
            console.log("登录失败: 用户名或密码错误");
            res.json({success: false});
        }
    })
})

// 保留其他现有接口(如retrieveStrategies等)

app.listen(3001, () => {
    console.log("running on port 3001");
})

后端修改说明

  • 移除全局变量auth:直接在POST请求的数据库查询回调中返回验证结果,避免全局状态共享的混乱。
  • 修正查询结果判断逻辑:用result.length > 0判断是否存在匹配用户,替代错误的result != null。
  • 增加错误处理:捕获数据库查询错误,返回500状态码和错误信息,避免请求挂起。
  • 直接返回JSON结果:前端可直接通过响应体获取验证状态,无需额外发送GET请求。

额外优化建议

  • 后端userIdG全局变量存在多用户并发问题,建议改用Session或JWT令牌存储用户身份信息,避免用户信息互相覆盖。
  • 目前登录逻辑未使用Access Code(OTP),建议补充OTP验证步骤提升安全性。
  • 数据库中不要明文存储密码,用bcrypt等加密算法哈希后再存储。

内容的提问来源于stack exchange,提问作者Adam Saleem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:45:45