使用axios / fetch从Node到React获取数据

huangapple go评论94阅读模式
英文:

Using axios / fetch to fetch data from node toreact

问题

我明白你的问题。以下是有关如何从Node后端到React前端获取数据的问题的翻译部分:

在你的React代码中,你尝试了两种方法来从Node后端获取数据,但遇到了问题。

第一种方法出现了401未授权错误,这可能是因为你的请求没有正确的身份验证。你需要确保在请求中包括有效的身份验证令牌(token)。你可以检查你的身份验证逻辑,确保令牌被正确设置并发送到后端。

第二种方法没有在控制台中返回任何内容,这可能是因为你没有正确地处理响应。在你的fetchData函数中,你可以尝试以下修改:

  1. const fetchData = async () => {
  2. try {
  3. const response = await fetch("http://localhost:4000/api/jobs", {
  4. method: "GET",
  5. headers: {
  6. "Content-Type": "application/json",
  7. Accept: "application/json",
  8. "Access-Control-Allow-Credentials": true,
  9. "Access-Control-Allow-Origin": true,
  10. credentials: "same-origin",
  11. Authorization: `Bearer ${token}`,
  12. },
  13. });
  14. if (!response.ok) {
  15. throw new Error("Network response was not ok");
  16. }
  17. const newData = await response.json();
  18. console.log(newData);
  19. setName(newData.jobs.name);
  20. } catch (error) {
  21. console.error("Fetch error:", error);
  22. }
  23. };
  24. fetchData();

这个修改将首先检查响应是否成功,如果不成功,则抛出一个错误。这有助于更好地处理错误情况并提供更多的信息来调试问题。

请确保在使用第二种方法时,你的token变量已经被定义和设置为有效的身份验证令牌。

希望这些修改能帮助你解决问题,成功获取数据从后端到前端。如果你需要进一步的帮助,请提供更多的信息。

英文:

Please I need a help on how to fetch a data from node to react, I have been stuck here for 2 weeks now.

Here are my backend code:

server.js:

  1. require("dotenv").config();
  2. const app = require("./src/app");
  3. const port = process.env.PORT || 4000;
  4. app.get("/", (req, res) => {
  5. res.send("Hello World!");
  6. });
  7. app.listen(port, () => {
  8. console.log(`Server is running on port http://localhost:${port}`);
  9. });

app.js:

  1. const express = require("express");
  2. const cors = require("cors");
  3. const cookieSession = require("cookie-session");
  4. const app = express();
  5. app.use(
  6. cors({
  7. origin: ["http://localhost:4000/api", "http://localhost:3000"],
  8. })
  9. );
  10. app.use(function (req, res, next) {
  11. res.header("Access-Control-Allow-Origin", "*");
  12. res.header(
  13. "Access-Control-Allow-Headers",
  14. "Origin, X-Requested-With, Content-Type, Accept"
  15. );
  16. next();
  17. });
  18. app.use(express.json());
  19. app.use(express({ type: "application/vnd.api+json" }));
  20. app.use(express.urlencoded({ extended: true }));
  21. app.use(
  22. cookieSession({
  23. name: process.env.COOKIE_NAME, //ookie name in .env
  24. secret: process.env.COOKIE_SECRET, //secret name in .env
  25. httpOnly: true,
  26. sameSite: "strict",
  27. maxAge: 24 * 60 * 60 * 1000, // 24 hours duration before expire
  28. })
  29. );
  30. app.use("/uploads", express.static("uploads"));
  31. const jobRoute = require("./routes/job.routes");
  32. app.use("/api/", jobRoute);
  33. module.exports = app;

service.js:

  1. const db = require("../config/database");
  2. const notificationServices = require("./notification.services");
  3. const { jobReuseQuery } = require("../job reuseable query/job.queries");
  4. const createJob = async (body) => {
  5. const {
  6. title,
  7. salary_type,
  8. salary,
  9. job_types,
  10. description,
  11. company_id,
  12. sector_id,
  13. category_id,
  14. } = body;
  15. const { rows } = await db.query(
  16. `INSERT INTO jobs (title, salary_type, salary, job_types, description, company_id, sector_id, category_id)
  17. VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`,
  18. [
  19. title,
  20. salary_type,
  21. salary,
  22. job_types,
  23. description,
  24. company_id,
  25. sector_id,
  26. category_id,
  27. ]
  28. );
  29. notificationServices.sendMatchJobsToUserProfiles(rows[0]);
  30. return rows[0];
  31. };
  32. const getAllJobs = async () => {
  33. const { rows } = await db.query("SELECT * FROM jobs");
  34. return rows;
  35. };

controller.js:

  1. const jobService = require("../services/job.services");
  2. const createJob = async (req, res) => {
  3. try {
  4. const job = await jobService.createJob(req.body);
  5. res.status(201).send({
  6. message: "Job created successfully",
  7. data: job,
  8. });
  9. } catch (err) {
  10. res.status(400).send(err.message);
  11. }
  12. };
  13. const getAllJobs = async (req, res) => {
  14. try {
  15. const jobs = await jobService.getAllJobs();
  16. res.status(200).send({ data: jobs });
  17. } catch (err) {
  18. res.status(400).send({ message: err.message });
  19. }
  20. };

routes.js:

  1. const router = require("express-promise-router")();
  2. const jobController = require("../controllers/job.controller");
  3. const auth = require("../middleware/auth.middleware");
  4. router.post("/jobs", auth, jobController.createJob);

auth.js:

  1. const db = require("../config/database");
  2. const jwt = require("jsonwebtoken");
  3. const dotenv = require("dotenv");
  4. dotenv.config();
  5. const auth = async (req, res, next) => {
  6. const token = req.session.token;
  7. if (!token) {
  8. return res.status(401).send({ error: "Please Authenticate" });
  9. }
  10. try {
  11. const decoded = jwt.verify(token, process.env.JWT_SECRET);
  12. const { rows } = await db.query("SELECT * FROM users WHERE id = $1", [
  13. decoded.id,
  14. ]);
  15. if (!rows[0]) {
  16. throw new Error("User not found");
  17. }
  18. req.user = rows[0];
  19. next();
  20. } catch (error) {
  21. return res.status(401).send({ error: error.message });
  22. }
  23. };
  24. module.exports = auth;

React frontend code:

  1. import React, { useEffect } from "react";
  2. import tech from "../../image/tech-big.svg";
  3. import health from "../../image/health-big.svg";
  4. import eng from "../../image/eng-big.svg";
  5. import axios from "axios";
  6. import { useState } from "react";
  7. const Joblist = () => {
  8. const [name, setName] = useState([]);
  9. //first method
  10. const response = axios
  11. .get("http://localhost:4000/api/jobs/")
  12. .then((res) => res.json());
  13. console.log(response);
  14. //second method
  15. const fetchData = async () => {
  16. const newData = await fetch("http:localhost:4000/api/jobs", {
  17. method: "GET",
  18. headers: {
  19. "Content-Type": "application/json",
  20. ACCEPT: "application/json",
  21. "Access-Control-Allow-Credentials": true,
  22. "Access-Control-Allow-Origin": true,
  23. credentials: "same-origin",
  24. Authorization: `Bearer ${token}`,
  25. },
  26. }).then((res) => res.json());
  27. console.log(newData);
  28. setName(newData.jobs.name);
  29. fetchData();
  30. };

you can see in my react, I have 2 method i used trying to fetch the data fron node to the react

first method return error in my browser console :

  1. Promise {<pending>}
  2. GET http://localhost:4000/api/jobs/ 401 (Unauthorized)
  3. Uncaught (in promise) AxiosError {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}

while the second method return nothing in my browser console

I am trying to fetch a data from my node backend into frontend react but my first method log error while the second method log nothing

答案1

得分: 0

我认为你需要稍微清理一下你的设置,因为你正在使用CORS,你可以首先进行一些更改:

  1. // .....
  2. const app = express();
  3. // 使用CORS,你可以在同一个地方进行所有设置,所以不需要设置头信息
  4. const corsOptions = {
  5. origin: ["http://localhost:4000/api", "http://localhost:3000"],
  6. methods: "GET, POST, PUT, DELETE, OPTIONS, HEAD",
  7. credentials: true, // 用于JWT/cookie!
  8. };
  9. app.use(cors(corsOptions));
  10. app.use(express.json());
  11. app.use(express({ type: "application/vnd.api+json" }));
  12. app.use(express.urlencoded({ extended: true }));
  13. app.use(
  14. cookieSession({
  15. name: process.env.COOKIE_NAME,
  16. secret: process.env.COOKIE_SECRET,
  17. maxAge: 24 * 60 * 60 * 1000,
  18. httpOnly: true,
  19. sameSite: false, //如果部署到跨域生产环境,请设置为"None"。
  20. secure: false, //如果在https的生产环境中需要,请设置为true
  21. });
  22. );
  23. app.use("/uploads", express.static("uploads"));
  24. const jobRoute = require("./routes/job.routes");
  25. app.use("/api/", jobRoute);
  26. module.exports = app;

更新fetch部分,我进行了清理(删除了头信息),我注意到你在job.controller.js中将数据属性放在了响应JSON中,所以你需要再次检查你的数据库结构是否正常工作。

  1. useEffect(() => {
  2. const fetchData = async () => {
  3. try {
  4. const response = await fetch("http:localhost:4000/api/jobs", {
  5. credentials: "include", //以便能够发送带有cookies的请求...
  6. });
  7. if(response.ok) {
  8. const newData = await response.json();
  9. console.log(newData);
  10. setName(newData.data.jobs.name); //这部分你需要再次检查你的数据结构...
  11. }
  12. } catch (error) {
  13. console.log(error)
  14. }
  15. }
  16. fetchData();
  17. }, []);

可选注意事项:这部分不是你的问题的一部分,只是以防cookie-session和JWT令牌仍然存在问题,你可以更改JWT在cookie中的存储方式:cookie-session的目的是创建一个“会话ID”,通过在客户端(浏览器)上存储它(在cookie中)来进行用户身份验证,如果你要使用JWT令牌进行身份验证,我真的看不出为什么要使用它?如果你在这部分仍然遇到问题,你可以查看下面的步骤:

首先,你可能需要安装cookie-parser中间件,因为如果这种方法对你有效,你将能够卸载cookie-session。

  1. const cookieParser = require('cookie-parser')
  2. // ...
  3. app.use(cookieParser());

在auth.controllers.js中:

  1. const loginAuth = async (req, res) => {
  2. try {
  3. const token = await authServices.login(req.body);
  4. // 在cookie中设置JWT令牌
  5. res.cookie("jwt", token, {
  6. maxAge: 24 * 60 * 60 * 1000,
  7. httpOnly: true,
  8. sameSite: false, //如果部署到跨域生产环境,请设置为"None"。
  9. secure: false, //如果在https的生产环境中需要,请设置为true
  10. })
  11. return res.status(200).json({
  12. //如果发送的请求体匹配,控制器将返回此消息
  13. message: "用户登录成功!",
  14. });
  15. } catch (error) {
  16. //否则将返回此错误消息
  17. return res.status(500).json({ message: error.message });
  18. }
  19. };
  20. // 为用户创建注销会话,将会话签名为空
  21. const logoutAuth = async (req, res) => {
  22. res.clearCookie("jwt")
  23. return res.status(200).send({ message: "用户成功登出!" });
  24. };

还需要在activeAuth函数中替换const token = req.session.token;,在auth.middleware.js的auth中间件函数中替换为:

  1. const token = req.cookies["jwt"] //或者
  2. const token = req.cookies.jwt

最后,如果它工作了,你可以卸载cookie-session。

英文:

I think you need to clean up a bit your setting, since you're using CORS than you can first make some changes :

  1. // .....
  2. const app = express();
  3. // with CORS you can do all your setting at the same place, so you don't need to set the header
  4. const corsOptions = {
  5. origin: ["http://localhost:4000/api", "http://localhost:3000"],
  6. methods: "GET, POST, PUT, DELETE, OPTIONS, HEAD",
  7. credentials: true, // for jwt/cookie !
  8. };
  9. app.use(cors(corsOptions));
  10. app.use(express.json());
  11. app.use(express({ type: "application/vnd.api+json" }));
  12. app.use(express.urlencoded({ extended: true }));
  13. app.use(
  14. cookieSession({
  15. name: process.env.COOKIE_NAME,
  16. secret: process.env.COOKIE_SECRET,
  17. maxAge: 24 * 60 * 60 * 1000,
  18. httpOnly: true,
  19. sameSite: false, //set this to "None" if you deploy to production on cross domaine.
  20. secure: false, //set to true is required on production with https
  21. });
  22. app.use("/uploads", express.static("uploads"));
  23. const jobRoute = require("./routes/job.routes");
  24. app.use("/api/", jobRoute);
  25. module.exports = app;

Update the fetch part I clean up (I remove the header) and i just notice on your job.controller.js you put data property on your response json.. so you need to check again your database structure if it's still not working.

  1. useEffect(() => {
  2. const fetchData = async () => {
  3. try {
  4. const response = await fetch("http:localhost:4000/api/jobs", {
  5. credentials: "include", //to be able to send with cookies...
  6. });
  7. if(response.ok) {
  8. const newData = await response.json();
  9. console.log(newData);
  10. setName(newData.data.jobs.name); // this part you need to check your data structure again...
  11. }
  12. } catch (error) {
  13. console.log(error)
  14. }
  15. }
  16. fetchData();
  17. }, []);

Optional note: this part is not part of your question, just in case if there is still issue with the cookie-session and jwtoken, you can change how the JWT is stored in the cookie: cookie-session purpose is to create a "session id" to authenticate the user by storing it at the client side (on the browser, with the cookie), i don't really see the point to use this if you're gonna use jwt token to authenticate anyway ? I let you see the step below if you re still stuck at this part:

First, you may need to install cookie-parser middleware, because if this method work for you, you will be able to uninstall cookie-session.

  1. const cookieParser = require('cookie-parser')
  2. /...
  3. app.use(cookieParser());

on the auth.controllers.js

  1. const loginAuth = async (req, res) => {
  2. try {
  3. const token = await authServices.login(req.body);
  4. // set the jwt token on the cookie
  5. res.cookie("jwt", token, {
  6. maxAge: 24 * 60 * 60 * 1000,
  7. httpOnly: true,
  8. sameSite: false, //set this to "None" if you deploy to production on cross domaine.
  9. secure: false, //set to true is required on production with https
  10. })
  11. return res.status(200).json({
  12. //controller will return this message if the body sent was match
  13. message: "User logged in successfully!",
  14. });
  15. } catch (error) {
  16. //ratther it will return this erroe message
  17. return res.status(500).json({ message: error.message });
  18. }
  19. };
  20. //create a logout session for the user to logout by signing session to null
  21. const logoutAuth = async (req, res) => {
  22. res.clearCookie("jwt")
  23. return res.status(200).send({ message: "User logged out successfully!" });
  24. };

You also need to replace const token = req.session.token; in your activeAuth function, and in your auth.middleware.js at the auth middleware function by this:

  1. const token = req.cookies["jwt"] //or
  2. const token = req.cookies.jwt

Finally if it work you can uninstall cookie-session.

huangapple
  • 本文由 发表于 2023年1月9日 03:25:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050662.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定