我已经在后端使用 nodejs 制作了一个宁静的 API,这是我的文件夹结构:
├── server
│ ├── project.controller.js
│ ├── auth.js
│ └── project.routes.js
│ └── project.model.js
├── client
│ └── AddProjectModal.js
│ └── axios.service.js
│ └── auth-header.js
服务器 api 似乎工作正常,因为我可以使用邮递员执行 CRUD 操作,但是如果我尝试从响应的客户端发送 post 请求,我不知何故无法继续。我尝试使用 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) 查看是否正在传入数据,当我使用邮递员发布请求时,我得到了以下结果:
这是我从浏览器请求时的结果,我得到了空对象:
答案 0 :(得分:1)
区别在于请求的格式。在 Postman 中,您将数据作为 JSON 对象发送。在客户端代码中,您在表单数据中发送数据。他们是不同的。这就是 req.body
为空的原因。 不同的请求格式要求服务器以不同的方式解析。
我在您的代码中看到 //formData.append("thumbnail", newProject.thumbnail);
行被注释,您准备在请求中发送项目的缩略图。在这种情况下,您无法以 JSON 格式发送请求。您需要修改服务器以使其理解表单数据。
为此,我推荐这个popular package
<块引用>Multer 是一个用于处理 multipart/form-data 的 node.js 中间件,它 主要用于上传文件。
答案 1 :(得分:0)
我通过使用 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} 代替!
答案 2 :(得分:0)
更新
正如 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