reactjs Axios 404在对Express服务器的POST请求中出现找不到错误

vxf3dgd4  于 2023-03-08  发布在  React
关注(0)|答案(3)|浏览(121)

我正在开发一个预订应用程序,并尝试实现身份验证,因此当我从 Postman 发送POST请求时,我会获得用户信息,但当使用axios库从react应用程序发送POST请求时,我会收到404未找到错误
这是登录中不同事件的AuthContext页面

import { createContext, useEffect, useReducer } from "react";

const INITIAL_STATE = {
  user: JSON.parse(localStorage.getItem("user")) || null,
  loading: false,
  error: null,
};

export const AuthContext = createContext(INITIAL_STATE);

const AuthReducer = (state, action) => {
  switch (action.type) {
    case "LOGIN_START":
      return {
        user: null,
        loading: true,
        error: null,
      };
    case "LOGIN_SUCCESS":
      return {
        user: action.payload,
        loading: false,
        error: null,
      };
    case "LOGIN_FAILURE":
      return {
        user: null,
        loading: false,
        error: action.payload,
      };
    case "LOGOUT":
      return {
        user: null,
        loading: false,
        error: null,
      };
    default:
      return state;
  }
};

export const AuthContextProvider = ({ children }) => {
  const [state, dispatch] = useReducer(AuthReducer, INITIAL_STATE);

  useEffect(() => {
    localStorage.setItem("user", JSON.stringify(state.user));
  }, [state.user]);

  return (
    <AuthContext.Provider
      value={{
        user: state.user,
        loading: state.loading,
        error: state.error,
        dispatch,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

这是登录页面代码

import axios from "axios";
import { useContext, useState } from "react";
import { AuthContext } from "../../context/AuthContext";
import { useNavigate } from "react-router-dom";
import "./login.css";

const Login = () => {
  const [credentials, setCredentials] = useState({
    username: undefined,
    password: undefined,
  });

  const {user,  loading, error, dispatch } = useContext(AuthContext);

  const navigate = useNavigate();

  const handleChange = (e) => {
    setCredentials((prev) => ({ ...prev, [e.target.id]: e.target.value }));
  };

  const handleClick = async (e) => {
    e.preventDefault();
    dispatch({ type: "LOGIN_START" });
    try {
      const res = await axios.post("/auth/login", credentials);
      dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
      navigate("/");
    } catch (err) {
      dispatch({ type: "LOGIN_FAILURE", payload: err.response.data });
    }
  };

  return (
    <div className="login">
      <div className="lContainer">
        <input
          type="text"
          placeholder="username"
          id="username"
          onChange={handleChange}
          className="lInput"
        />
        <input
          type="password"
          placeholder="password"
          id="password"
          onChange={handleChange}
          className="lInput"
        />
        <button disabled={loading} onClick={handleClick} className="lButton">
          Login
        </button>
        {error && <span>{error.message}</span>}
      </div>
    </div>
  );
};

export default Login;

我使用代理"proxy": "http://localhost:8800/api"将前端与Express服务器连接
这是package.json文件

{
  "name": "hotel-moment",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^6.2.1",
    "@fortawesome/free-regular-svg-icons": "^6.2.1",
    "@fortawesome/free-solid-svg-icons": "^6.2.1",
    "@fortawesome/react-fontawesome": "^0.2.0",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.2.4",
    "date-fns": "^2.29.3",
    "http-proxy-middleware": "^2.0.6",
    "react": "^18.2.0",
    "react-date-range": "^1.4.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.4.4",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "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"
}

这些是登录路由的控制器

import User from "../models/User.js";
import bcrypt from "bcrypt";
import { createError } from "../utils/error.js";
import jwt from "jsonwebtoken";

// Sign Up user function
export const register = async (req, res, next) => {
    try {

        const salt = bcrypt.genSaltSync(10);
        const hash = bcrypt.hashSync(req.body.password, salt);

        const newUser = new User({
            username: req.body.username,
            email: req.body.email,
            password: hash,
        });

        await newUser.save();
        res.status(200).send("User has been created");
    } catch(err) {
        next(err);
    }
}

// Login user function
export const login = async (req, res, next) => {
    try {

        const user = await User.findOne({username: req.body.username});
        if(!user) return next(createError(404, "User not found"));

        const isPasswordCorrect = await bcrypt.compare(req.body.password, user.password);

        const token = jwt.sign({ id:user._id, isAdmin: user.isAdmin }, process.env.JWT_TOKEN);

        if(!isPasswordCorrect) return next(createError(400, "Incorrct password or username"));
        const {password, isAdmin, ...otherDetails} = user._doc;
        res
        .cookie("access_token", token, {
            httpOnly: true,
        })
        .status(200)
        .json({...otherDetails});
    } catch(err) {
        next(err);
    }
}

我尝试使用promises执行相同的操作,但仍然得到相同的错误。我不明白为什么会得到此错误
Error 404 Not Found
但在 Postman 里我得到了这样的回应
Postman respose
请帮我解决这个错误,我会非常感谢你

laik7k3q

laik7k3q1#

你能试一下下面的代码吗?

const handleClick = async (e) => {
    const config = {
      url: "http://localhost:8800/api/auth/login",
      data: credentials
    };

    e.preventDefault();
    dispatch({ type: "LOGIN_START" });
    try {
      const res = await axios.post(config);
      dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
      navigate("/");
    } catch (err) {
      dispatch({ type: "LOGIN_FAILURE", payload: err.response.data });
    }
};
ffscu2ro

ffscu2ro2#

您是否在包.json中添加了代理?

"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/"
6vl6ewon

6vl6ewon3#

你的前端和后端都在两个不同的端口上。如果你在谷歌控制台检查你的错误,它会给出http://localhost:3000,但你的后端在http://localhost:8800。现在你需要为axios添加配置。告诉他使用http://localhost:8800。

const instance = axios.create({baseURL: 'http://localhost:8800/api'});

这里我们添加了http://localhost:8800作为axios的BaseUrl,现在可以在handleClick方法中使用instance.post("/auth/login", credentials)
您可以为创建Axios示例创建一个单独的文件,并在您想要使用的地方使用它。

import axios from 'axios';
const instance = axios.create({baseURL: 'http://localhost:8800/api'});
export default instance

现在你可以导入示例而不是axios了,这样就保存每次API调用都配置axios了。

相关问题