【问题标题】:Axios POST does not recognize the data being passed in from reactAxios POST 无法识别从 react 传入的数据
【发布时间】:2021-06-10 14:35:48
【问题描述】:

我已经在后端使用 nodejs 制作了一个 restful API,这是我的文件夹结构:

├── server
│   ├── project.controller.js
│   ├── auth.js
│   └── project.routes.js
│   └── project.model.js
├── client
│   └── AddProjectModal.js
│   └── axios.service.js
│   └── auth-header.js

服务器 api 似乎工作正常,因为我可以使用邮递员执行 CRUD 操作,但是如果我尝试从响应的客户端发送发布请求,我不知何故无法继续。我尝试了几个小时使用 console.log 进行自我调试,以找出我做错的地方,但我找不到任何东西。

这是我的 AddProjectModal.js:

import React, { useState } from "react";
import { authAxios } from "../../services/axios.service";

const AddProjectModal = ({ isShow, isClose }) => {
  const [newProject, setNewProject] = useState({
    title: "",
    type: "",
    description: "",
    //thumbnail: "",
  });

  const handleUpload = async (e) => {
    e.preventDefault();
    var formData = new FormData();
    formData.append("title", newProject.title);
    formData.append("type", newProject.type);
    formData.append("description", newProject.description);
    // formData.append("thumbnail", newProject.thumbnail);
    console.log(...formData);
    try {
      await authAxios
        .post("/api/project/", formData)
        .then((res) => {
          console.log(res.data);
        })
        .catch((e) => {
          console.log(e);
        });
    } catch (err) {
      console.log(err);
    }
  };

.... 
}

如您所见,我尝试使用 console.log(...formData) 查看数据是否已成功附加,并且确实如此。这是示例结果:

这是我的 axios.service.js 代码:

import axios from "axios";
import authHeader from "./auth-header";

const apiUrl = "http://localhost:5000/";

export const authAxios = axios.create({
  baseURL: apiUrl,
  headers: authHeader(),
});

export const publicAxios = axios.create({
  baseURL: apiUrl,
});

我的 auth-header.js 代码:

const authHeader = () => {
  const user = JSON.parse(localStorage.getItem("user"));

  if (user && user.accessToken) {
    return { "x-access-token": user.accessToken };
  } else {
    return {};
  }
};

export default authHeader;

还有我的后端代码:

project.routes.js:

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

const auth = require("../../middleware/auth");
const controller = require("../../controllers/project.controller");

//Upload new project
router.post("/", auth, controller.createProject);


module.exports = router;

project.controller.js:

const Project = require("../models/project.model");
// create & save new project
exports.createProject = async (req, res, next) => {
  console.log(req.body);
  if (!req.body.title || !req.body.type || !req.body.description) {
    res.status(400).send({ message: "Form cant be empty!" });
    return;
  }

  try {
    //create project
    const project = new Project({
      title: req.body.title,
      type: req.body.type,
      description: req.body.description,
    });
    // save project to the database
    const createdProject = await project.save();
    res.send(createdProject);
  } catch (err) {
    console.log("err" + err);
    res.status(500).send(err);
    next(err);
  }
};

在上面的代码中,我试图通过 console.log(req.body) 查看数据是否正在传入,当我使用邮递员发布请求时,我得到了这个结果:

这是我从浏览器请求时的结果,我得到了空对象:

由于我能够从 Postman 发出请求,我认为问题不在我的服务器端,这是我尝试从浏览器发出 post 请求时的结果:

【问题讨论】:

  • 首先你应该像res.json({}) 一样将res作为json发送,并且在你的catch块中你不应该再发送响应,因为据我所知你正在使用错误处理程序中间件(下一个(错误)),而且我认为您有 cors 政策问题控制台在前面记录错误,看看您是否遇到 cors 政策问题

标签: node.js reactjs express axios


【解决方案1】:

解释

  • 为什么它适用于 Postman 而不适用于客户端代码?

区别在于请求的格式。在 Postman 中,您将数据作为 JSON 对象发送。在客户端代码中,您在表单数据中发送数据。它们是不同的。这就是req.body 为空的原因。 不同的请求格式需要服务器以不同的方式解析

动作

我在您的代码中看到//formData.append("thumbnail", newProject.thumbnail); 行被注释,您准备在请求中发送项目的缩略图。在这种情况下,您无法以 JSON 格式发送请求。您需要修改服务器以使其能够理解表单数据。

为此,我推荐这个popular package

Multer 是一个用于处理 multipart/form-data 的 node.js 中间件,它 主要用于上传文件。

【讨论】:

  • 在阅读了您关于表单需要以不同方式处理的建议后,我明白了,我最终使用 react-hooks-form 进行验证,并成功将其发送到我的数据库!
【解决方案2】:

我通过使用react-hook-form 库解决了这个问题。像这样编辑我的 AddProjectModal.js :

import axios from "axios";
import React, { useState } from "react";
import { Button, Modal, Form } from "react-bootstrap";
import { Controller, useForm } from "react-hook-form";

import { authAxios } from "../../services/axios.service";

const AddProjectModal = ({ isShow, isClose }) => {
  const { control, handleSubmit } = useForm({
    defaultValues: {
      title: "",
      type: "",
      description: "",
      thumbnail: "",
    },
  });
  const onSubmit = async (data) => {
    try {
      setLoading(true);
      await authAxios
        .post("/api/project/", data)
        .then((res) => {
          console.log(res.data);
        })
        .catch((e) => {
          console.log(e);
        });
    } catch (err) {
      console.log(err);
    }
  };
  
  return (
    <Modal show={isShow === "modal-one"} onHide={isClose}>
      <Modal.Header>
        <Modal.Title>Tambahkan Project</Modal.Title>
      </Modal.Header>
      <Modal.Body>
        <form encType="multipart/form-data">
          <Form.Group controlId="title">
            <Form.Label>Judul Project</Form.Label>
            <Controller
              control={control}
              name="title"
              render={({ field: { onChange, value } }) => (
                <Form.Control
                  type="text"
                  placeholder="Nama Project"
                  onChange={onChange}
                  value={value}
                />
              )}
            />
          </Form.Group>
          <Form.Group controlId="type">
            <Form.Label>Jenis Projek : </Form.Label>
            <Controller
              control={control}
              name="type"
              render={({ field: { onChange, value } }) => (
                <Form.Control as="select" onChange={onChange} value={value}>
                  <option value=""> </option>
                  <option value="web apps">Web Apps</option>
                  <option value="mobile apps">Mobile Apps</option>
                  <option value="landing page">Landing Page</option>
                </Form.Control>
              )}
            />
          </Form.Group>
          <Form.Group controlId="description">
            <Form.Label>Deskripsi Projek</Form.Label>
            <Controller
              control={control}
              name="description"
              render={({ field: { onChange, value } }) => (
                <Form.Control
                  as="textarea"
                  rows={3}
                  value={value}
                  onChange={onChange}
                />
              )}
            />
          </Form.Group>
          <Form.Group>
            <label>Foto Anda</label>
            <Controller
              control={control}
              name="thumbnail"
              render={({ field: { onChange, value } }) => (
                <Form.File
                  type="file"
                  id="thumbnail"
                  onChange={onChange}
                  value={value}
                />
              )}
            />
          </Form.Group>
        </form>
      </Modal.Body>
      <Modal.Footer>
        <Button type="submit" onClick={handleSubmit(onSubmit)}>
          Upload
        </Button>
        <Button onClick={isClose}>Close</Button>
      </Modal.Footer>
    </Modal>
  );
};

export default AddProjectModal;

对我来说,问题是我以前的表单不会发送输入的数据。使用 react-hook-form 后,基本上我存储了所有传递到 {control} 的数据(因为我使用自定义组件 react- bootstrap ) ,如果你使用普通形式,你可以使用 {register} 代替!

【讨论】:

    【解决方案3】:

    更新

    正如 Dang Khoa 所说,他建议安装 multer 来处理表单数据类型。如果您不想使用 react-hooks-form ,您仍然可以通过安装 multer 并在服务器上编辑 index.js / app.js 以包含 multer 来处理表单数据类型:

    const express = require("express");
    const mongoose = require("mongoose");
    const cors = require("cors"); // this
    const multer = require("multer");
    require("dotenv").config();
    
    const app = express();
    const upload = multer();
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(cors());
    app.use(upload.array()); // and this
    //cors

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多