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

React中使用useEffect+Axios调用后端API遇404错误求助

Netflix克隆项目React请求404错误排查思路

开发Netflix克隆项目时,使用React的useEffect钩子调用后端API获取MongoDB电影列表时遇到404错误,Postman请求正常但React中报错,以下是具体排查方向:

核心排查点

1. 修复前端请求路径的相对路径问题

前端请求路径写的是lists(无开头斜杠),会导致请求相对于当前页面路由(比如当前页面是http://localhost:3000/home,实际请求会变成http://localhost:3000/home/lists),完全没有触发代理转发。

解决方法:给请求路径加上开头斜杠,修改后代码如下:

const res = await axios.get(
  `/lists${type ? "?type=" + type : ""}${genre ? "&genre=" + genre : ""}`,
  // ...其他配置
);

2. 验证代理配置是否生效

打开浏览器开发者工具的Network标签,查看请求的完整URL:

  • 如果请求地址是http://localhost:3000/lists:说明代理没生效,检查路径是否带斜杠,或者重启React开发服务器(proxy配置修改后必须重启)。
  • 如果请求地址是http://localhost:8800/api/lists:说明代理已生效,继续排查其他问题。

3. 确认后端路由拼接逻辑

后端index.js中挂载list路由的代码是app.use("/api/lists", listRoute);,而list.js中的GET路由是router.get("/", ...),完整的后端接口路径是http://localhost:8800/api/lists,和前端带斜杠的请求/lists加上代理http://localhost:8800/api/拼接后的路径一致,这部分逻辑是正确的。

4. 检查请求头的token有效性

虽然Postman请求正常,但要确认前端发送的token是否和Postman中一致,以及后端的verify中间件是否会因为token问题返回404(部分权限拦截逻辑可能错误返回404而非403)。可以暂时注释掉verify中间件,测试请求是否能成功,排除权限验证的影响。

5. 重启React开发服务器

proxy配置修改后,必须重启React的npm start服务,否则新的代理配置不会生效。


相关代码参考

package.json 文件

{
  "name": "new",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.11.4",
    "@material-ui/icons": "^4.11.2",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "axios": "^0.21.1",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.3",
    "sass": "^1.35.1",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "proxy": "http://localhost:8800/api/"
}

Home.jsx

import { useEffect, useState } from "react";
import Featured from "../../components/featured/Featured";
import List from "../../components/list/List";
import Navbar from "../../components/navbar/Navbar";
import axios from "axios";
import "./home.scss";

const Home = ({ type }) => {
  // eslint-disable-next-line
  const [lists, setLists] = useState([]);
  // eslint-disable-next-line
  const [genre, setGenre] = useState(null);

  useEffect(() => {
    const getRandomLists = async () => {
      try {
        const res = await axios.get(
          `/lists${type ? "?type=" + type : ""}${genre ? "&genre=" + genre : ""}`,
          {
            headers: {
              token:
                "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzYTA1ZjliZTRiZmEzYTBhOWMxYTQ5ZCIsImlzQWRtaW4iOnRydWUsImlhdCI6MTY3MTcxMjgyMCwiZXhwIjoxNjcyMTQ0ODIwfQ.W2e-RJ0XIQIVgGT47yhEOVOtWbdR5yYk11zmvN3vLzk",
            },
          }
        );
        console.log(res);
      } catch (error) {
        console.log(error);
      }
    };
    getRandomLists();
  }, [type, genre]);
  return (
    <div className="home">
      <Navbar />
      <Featured type={type} />
      <List />
      <List />
      <List />
      <List />
      <List />
      <List />
    </div>
  );
};

export default Home;

后端index.js

const express = require("express");
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const authRoute = require("./routes/auth");
const userRoute = require("./routes/users");
const movieRoute = require("./routes/movies");
const listRoute = require("./routes/lists");
const cors = require("cors");

app.use(cors());
dotenv.config();

mongoose
  .connect(process.env.MONGO_URL, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(() => console.log("DB Connection Successful!"))
  .catch((err) => console.log(err));

app.use(express.json());

app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.use("/api/movies", movieRoute);
app.use("/api/lists", listRoute);

app.listen(8800, () => {
  console.log("backend server is running on port 8800");
});

后端list.js

router.get("/", verify, async (req, res) => {
  const typeQuery = req.query.type;
  const genreQuery = req.query.genre;
  let list = [];

  try {
    if (typeQuery) {
      if (genreQuery) {
        list = await List.aggregate([
          { $sample: { size: 10 } },
          { $match: { type: typeQuery, genre: genreQuery } },
        ]);
      } else {
        list = await List.aggregate([
          { $sample: { size: 10 } },
          { $match: { type: typeQuery } },
        ]);
      }
    } else {
      list = await List.aggregate([{ $sample: { size: 10 } }]);
    }
    res.status(200).json(list);
  } catch (error) {
    res.status(500).json(error);
  }
});

内容的提问来源于stack exchange,提问作者john s

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:55:52