仅当POST请求返回403时阻止React Link跳转的问题排查
问题描述
我要实现的逻辑是:当创建房间的POST请求返回403 Forbidden(房间名已存在于Lobbies.json)时,阻止React的Link组件跳转;请求成功则正常跳转。但现在代码里的.then函数完全没执行(控制台看不到"Testing"输出),没法实现预期逻辑,求帮忙排查原因。
相关代码
Lobbies.json
{"Lobbies":[]}
jsonWorker.js
const fs = require('fs'); function lobbyUpdater(name, password) { let rawdata = fs.readFileSync('Lobbies.json'); let data = JSON.parse(rawdata); // data.Lobbies.length = 0; // Remove this for production let newLobby = {"Name":name, "Password":password, "Players":1, "Mode":"", "Word":""} data.Lobbies.push(newLobby) fs.writeFile('Lobbies.json', JSON.stringify(data), 'utf8', function(err) { if (err) throw err; }); } function lobbyAvailable(name) { let rawdata = fs.readFileSync('Lobbies.json'); let data = JSON.parse(rawdata); for (let i = 0; i < data.Lobbies.length; i++) { if (data.Lobbies[i].Name.toUpperCase() === name.toUpperCase()) { return false; } } return true; } module.exports = { lobbyUpdater, lobbyAvailable };
后端index.js中的POST请求处理
app.post('/newLobby', (req, res) => { console.log("Lobby Name:", req.body.lobbyName); console.log("Lobby Password:", req.body.lobbyPassword); const jsonWorker = require('./jsonWorker'); if (jsonWorker.lobbyAvailable(req.body.lobbyName)) { jsonWorker.lobbyUpdater(req.body.lobbyName, req.body.lobbyPassword); } else { res.sendStatus(403); console.log("Stopped A Lobby From Being Created"); } });
React组件代码
<Link id="testLink" to="/Waiting-For-Players"><button id="submit" onClick={sendingRequest} className="WaitingForPlayers">Create Lobby</button></Link>
sendingRequest函数
function sendingRequest(event) { event.preventDefault(); $.post("http://localhost:4000/newLobby", { lobbyName: document.getElementById('lobbyName').value, lobbyPassword: document.getElementById('lobbyPassword').value }, function (data, status) { console.log("Data", data); }) .fail(function(jqXHR, textStatus, errorThrown) { console.log("Error received:", errorThrown); console.log("Stopping the post request."); return; }) .then(function() { // Follow the Link component let linkToUse = document.getElementById("testLink"); window.location.assign(linkToUse.to); console.log("Testing") }); }
问题排查与修复
1. 后端未返回成功响应
当前后端代码里,房间创建成功时没有给前端返回任何响应(没调用res.send/res.sendStatus),导致前端AJAX请求一直处于等待状态,.then自然不会触发。
修复后端代码:
app.post('/newLobby', (req, res) => { console.log("Lobby Name:", req.body.lobbyName); console.log("Lobby Password:", req.body.lobbyPassword); const jsonWorker = require('./jsonWorker'); if (jsonWorker.lobbyAvailable(req.body.lobbyName)) { jsonWorker.lobbyUpdater(req.body.lobbyName, req.body.lobbyPassword); // 添加成功响应,告诉前端请求完成 res.sendStatus(201); // 也可以用res.json({success: true})返回更多信息 } else { res.sendStatus(403); console.log("Stopped A Lobby From Being Created"); } });
2. jQuery AJAX链式调用逻辑问题
原代码把跳转逻辑放在.then里,但.fail回调的return不会中断链式调用,而且.then不管成功失败都会执行。应该把跳转逻辑放到.done(仅成功时触发)里,失败时不做处理即可:
修改sendingRequest函数:
function sendingRequest(event) { event.preventDefault(); $.post("http://localhost:4000/newLobby", { lobbyName: document.getElementById('lobbyName').value, lobbyPassword: document.getElementById('lobbyPassword').value }) .done(function(data, status) { console.log("Data", data); // 仅请求成功时跳转 let linkToUse = document.getElementById("testLink"); // 注意:React Link的to是组件属性,不是DOM元素属性,直接拿会出错,建议直接写路径 window.location.assign('/Waiting-For-Players'); console.log("Testing"); }) .fail(function(jqXHR, textStatus, errorThrown) { console.log("Error received:", errorThrown); console.log("房间名已存在,无法创建"); // 失败时不执行跳转逻辑 }); }
3. React Router跳转方式优化
原代码用window.location.assign跳转违背了React单页应用的逻辑,更推荐用React Router的钩子来处理:
以React Router v6为例:
import { useNavigate } from 'react-router-dom'; function YourComponent() { const navigate = useNavigate(); function sendingRequest(event) { event.preventDefault(); $.post("http://localhost:4000/newLobby", { lobbyName: document.getElementById('lobbyName').value, lobbyPassword: document.getElementById('lobbyPassword').value }) .done(function() { // 成功后跳转 navigate('/Waiting-For-Players'); console.log("Testing"); }) .fail(function(jqXHR) { if (jqXHR.status === 403) { console.log("房间名已存在,无法创建"); } }); } // 这里不需要Link组件了,跳转逻辑完全由js控制 return ( <button id="submit" onClick={sendingRequest} className="WaitingForPlayers">Create Lobby</button> ); }
内容的提问来源于stack exchange,提问作者Happyface456
相关产品推荐
相关产品推荐

