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

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

关键修复步骤

  1. 调整后端启动顺序
    原代码中app.listen()写在路由定义之前,导致/api/register路由未被注册到Express应用。必须将app.listen()移到所有路由、中间件定义的最后位置,确保路由能被正常加载。

  2. 完善跨域凭证配置

    • 后端显式指定前端origin并开启credentials: true,允许跨域请求携带Session Cookie;
    • 前端fetch请求添加credentials: 'include',确保请求携带Cookie信息。
  3. 修复异常捕获参数
    后端catch块未接收error参数,导致无法打印具体错误信息,需改为catch(error)才能正常捕获并输出异常。

  4. 验证服务状态
    先在浏览器访问http://localhost:3002,确认返回"Hello, world!",证明后端服务正常运行;再用curl/Postman直接调用/api/register接口,测试服务器是否能接收请求。

内容的提问来源于stack exchange,提问作者Dillon Bishop

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:28:11