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

Express POST请求重定向失效:MERN栈React调用API异常

问题描述

我正在做一个MERN应用,现在处于API测试阶段:

  • 用纯HTML表单向/register发送POST请求时,一切功能正常;
  • 换成React + Axios调用后,/register请求能正常触发,但重定向到/api/users存储数据的操作失效,createUser函数里的console.log("this api has been called")完全没有输出。

相关代码如下:

后端代码

authorizationController的registerUser函数

exports.registerUser = async (req, res) => {
  const hashedPassword = md5(req.body.password);
  const newUser = new User({
    firstName: req.body.firstName,
    lastName: req.body.lastName,
    dateOfBirth: req.body.dateOfBirth,
    address: req.body.address,
    email: req.body.email,
    phoneNumber: req.body.phoneNumber,
    hash: hashedPassword,
  });
  req.session.newUser = newUser;
  console.log(req.session.newUser);
  await res.redirect(307, "/api/users");
};

userController的createUser函数

exports.createUser = (req, res) => {
  console.log("this api has been called");
  if (!req.session.newUser) {
    res.redirect("/");
    return;
  }
  const newUser = new User(req.session.newUser);
  newUser
    .save()
    .then((data) => {
      res.status(200).redirect("/register");
    })
    .catch((error) => {
      console.log(error);
      res.status(500).send({ message: "An error occured." });
    });
};

路由文件

const router = require("express").Router();

const userController = require("../controllers/userController");

router
  .route("/")
  .get(userController.getAllUsers)
  .post(userController.createUser)
  .delete(userController.deleteAllUsers);

router
  .route("/:_id")
  .get(userController.getUser)
  .put(userController.updateUser)
  .delete(userController.deleteUser);

module.exports = router;

前端React组件代码

import axios from "axios";
import { useState } from "react";

const initialValues = {
  firstName: "",
  lastName: "",
  dateOfBirth: "",
  email: "",
  password: "",
  address: "",
  phoneNumber: "",
};

function Register() {
  const [values, setValues] = useState(initialValues);

  const handleInputChange = (e) => {
    const { name, value } = e.target;

    setValues({
      ...values,
      [name]: value,
    });

    console.log({ ...values });
  };

  const handleSubmission = () => {
    console.log(values);
    axios.post("/register", values).then((res) => {
      console.log(res);
    });
  };

  return (
    <div>
      <h1>Register</h1>
      <form>
        <label style={{ display: "block" }}>
          First Name
          <input
            type="text"
            name="firstName"
            value={values.firstName}
            onChange={handleInputChange}
          />
        </label>
        <label style={{ display: "block" }}>
          Last Name
          <input
            type="text"
            name="lastName"
            value={values.lastName}
            onChange={handleInputChange}
          />
        </label>
        <label style={{ display: "block" }}>
          Date of Birth
          <input
            type="date"
            name="dateOfBirth"
            value={values.datefBirth}
            onChange={handleInputChange}
          />
        </label>

        <label style={{ display: "block" }}>
          Email
          <input
            type="email"
            name="email"
            value={values.email}
            onChange={handleInputChange}
          />
        </label>
        <label style={{ display: "block" }}>
          Password
          <input
            type="password"
            name="password"
            value={values.password}
            onChange={handleInputChange}
          />
        </label>
        <label style={{ display: "block" }}>
          address
          <input
            type="text"
            name="address"
            value={values.address}
            onChange={handleInputChange}
          />
        </label>
        <label style={{ display: "block" }}>
          Phone Number
          <input
            type="text"
            name="phoneNumber"
            value={values.phoneNumber}
            onChange={handleInputChange}
          />
        </label>
        <button onClick={handleSubmission}>Register</button>
      </form>
    </div>
  );
}

export default Register;

问题原因和解决办法

1. 表单默认提交行为打断了Axios请求

你React组件里的<button>没设置type="button",默认是submit类型,点击后会触发表单的默认提交行为——页面直接刷新,Axios的请求还没执行完就被中断,自然走不到后续的重定向步骤。

修复方式:
给按钮添加type="button"属性:

<button type="button" onClick={handleSubmission}>Register</button>

用Axios发送AJAX请求时,默认不会携带Cookie(里面存储着Session ID),导致服务器处理/api/users请求时,读取不到之前存在req.session.newUser的数据,直接重定向到/,createUser函数根本不会执行。

修复方式:

  • 全局配置Axios允许携带凭证,在React入口文件(如index.js)添加:
    axios.defaults.withCredentials = true;
    
  • 或者在单个请求中配置:
    修改handleSubmission函数:
    const handleSubmission = () => {
      console.log(values);
      axios.post("/register", values, { withCredentials: true })
        .then((res) => {
          console.log(res);
        })
        .catch(err => console.error(err));
    };
    
  • 若前后端为不同端口,后端需开启CORS并允许凭证:
    const cors = require('cors');
    app.use(cors({ credentials: true, origin: 'http://localhost:3000' })); // 替换为你的前端地址
    
  • 开发环境下,Express的Session配置不要设置secure: true,否则Cookie不会被发送:
    app.use(session({
      secret: 'your-secret-key',
      resave: false,
      saveUninitialized: false,
      cookie: { secure: false, sameSite: 'lax' }
    }));
    

3. 重定向逻辑不适合SPA场景

HTML表单的重定向是浏览器层面的页面跳转,但AJAX请求的重定向由XHR自动处理,后端返回的redirect对SPA应用意义不大,反而增加复杂度。

优化方案:
直接在registerUser函数中完成用户创建,无需重定向到/api/users:

exports.registerUser = async (req, res) => {
  try {
    const hashedPassword = md5(req.body.password);
    const newUser = new User({
      firstName: req.body.firstName,
      lastName: req.body.lastName,
      dateOfBirth: req.body.dateOfBirth,
      address: req.body.address,
      email: req.body.email,
      phoneNumber: req.body.phoneNumber,
      hash: hashedPassword,
    });
    const savedUser = await newUser.save();
    res.status(201).json({ message: "注册成功", user: savedUser });
  } catch (error) {
    console.log(error);
    res.status(500).json({ message: "出错了" });
  }
};

这样前端拿到返回的JSON后可直接处理,无需依赖Session和重定向,更符合SPA的开发模式。

另外注意:React组件中出生日期输入的value写为values.datefBirth(拼写错误,应为dateOfBirth),会导致出生日期无法正确传入,需修正:

<input
  type="date"
  name="dateOfBirth"
  value={values.dateOfBirth} // 修正拼写错误
  onChange={handleInputChange}
/>

内容的提问来源于stack exchange,提问作者Qoussay El Akkari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:50:48