React客户端与Express服务器无法通信问题排查求助
React前端与Express后端API请求无法送达问题排查
问题描述
React前端运行在3001端口,Express后端运行在3002端口,前端调用/api/register接口时提示Failed to fetch,且后端完全没有收到请求的日志记录,通信环节存在问题。
前端代码(CreateAccount.js)
// CreateAccount.js import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; function CreateAccount() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [email, setEmail] = useState(''); const navigate = useNavigate(); const handleSubmit = async (event) => { event.preventDefault(); const response = await fetch('http://localhost:3002/api/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', // 新增:跨域携带凭证 body: JSON.stringify({ username, password, email }), }); if (response.ok) { navigate('/my-account'); // 修正:路由路径无需加.js后缀 } } return ( <form onSubmit={handleSubmit}> <input type="text" placeholder="Username" value={username} onChange={e => setUsername(e.target.value)} required /> <input type="password" placeholder="Password" value={password} onChange={e => setPassword(e.target.value)} required /> <input type="email" placeholder="Email" value={email} onChange={e => setEmail(e.target.value)} required /> <button type="submit">Create Account</button> </form> ); } export default CreateAccount;
后端服务器代码
const cors = require('cors'); const express = require('express'); const app = express(); const port = 3002; const bcrypt = require('bcrypt'); const session = require('express-session'); const { Pool } = require('pg'); // 数据库连接配置 const pool = new Pool({ user: 'postgres', host: 'localhost', database: 'altuniai', password: process.env.DATABASE_PASSWORD, port: 5432, }); // 配置CORS:指定前端来源并允许跨域携带凭证 app.use(cors({ origin: 'http://localhost:3001', credentials: true })); app.use(express.urlencoded({ extended: true })); app.use(express.json()); // Session配置:优化跨域Cookie设置 app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { sameSite: 'lax', secure: false // 开发环境设为false,生产环境需改为true(HTTPS) } })); app.get('/', (req, res) => { res.send('Hello, world!'); }); // 注册接口 app.post('/api/register', async (req, res) => { try { console.log('Received a POST request to /api/register with data:', req.body); // 哈希密码 const hashedPassword = await bcrypt.hash(req.body.password, 10); // 存储新用户到数据库(假设createUser为已实现函数) const userId = await createUser(req.body.username, req.body.email, hashedPassword); console.log(`User created with id: ${userId}`); // 登录用户 req.session.userId = userId; // 返回成功响应 res.status(201).send({ userId: userId }); } catch (error) { // 修复:添加error参数捕获异常 console.error('Error while registering user: ', error); res.status(500).send({ message: '注册失败' }); } }); // 所有路由/中间件定义完成后再启动监听 app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); }); // 示例createUser函数(若未实现可参考) async function createUser(username, email, hashedPassword) { const result = await pool.query( 'INSERT INTO users (username, email, password) VALUES ($1, $2, $3) RETURNING id', [username, email, hashedPassword] ); return result.rows[0].id; }
报错信息
Uncaught (in promise) TypeError: Failed to fetch at handleSubmit (bundle.js:473:28) at HTMLUnknownElement.callCallback (bundle.js:15215:18) at Object.invokeGuardedCallbackDev (bundle.js:15259:20) at invokeGuardedCallback (bundle.js:15316:35) at invokeGuardedCallbackAndCatchFirstError (bundle.js:15330:29) at executeDispatch (bundle.js:19474:7) at processDispatchQueueItemsInOrder (bundle.js:19500:11) at processDispatchQueue (bundle.js:19511:9) at dispatchEventsForPlugins (bundle.js:19520:7) at bundle.js:19680:16
关键修复步骤
调整后端启动顺序
原代码中app.listen()写在路由定义之前,导致/api/register路由未被注册到Express应用。必须将app.listen()移到所有路由、中间件定义的最后位置,确保路由能被正常加载。完善跨域凭证配置
- 后端显式指定前端
origin并开启credentials: true,允许跨域请求携带Session Cookie; - 前端fetch请求添加
credentials: 'include',确保请求携带Cookie信息。
- 后端显式指定前端
修复异常捕获参数
后端catch块未接收error参数,导致无法打印具体错误信息,需改为catch(error)才能正常捕获并输出异常。验证服务状态
先在浏览器访问http://localhost:3002,确认返回"Hello, world!",证明后端服务正常运行;再用curl/Postman直接调用/api/register接口,测试服务器是否能接收请求。
内容的提问来源于stack exchange,提问作者Dillon Bishop
相关产品推荐
相关产品推荐

