reactjs - 使用 ReactJS 将对象数组发布到 REST API
问题描述
我正在做一个项目,我需要在我的 API 中发布一个新课程。我用 POSTMAN 对此进行了测试,API 工作得很好,但是当我尝试使用 react fetch 发布数据时,数据已损坏。虽然发送像dishName:“pizza”这样的单个字符串工作得很好并且显示在数据库中,但我无法发送对象数组。我尝试以多种方式做到这一点,例如:
[
{
"quantity": 1,
"unit": "",
"description": "egg"
},
{
"quantity": 0.5,
"unit": "cup",
"description": "mozzarella shredded"
}
]
或者:
{
"quantity": 1,
"unit": "",
"description": "egg"
},
{
"quantity": 0.5,
"unit": "cup",
"description": "mozzarella shredded"
}
还有很多很多的组合,但我失败了。
这是我的 React 类,它负责向 API 发送数据:
import React, { useState } from "react";
import { useHistory } from "react-router-dom";
export default function Login() {
const [dishName, setdishName] = useState("");
const [category, setcategory] = useState("");
const [author, setauthor] = useState("");
const [ingredients, setingredients] = useState([]);
const [cookingTime, setcookingTime] = useState("");
const [sourceUrl, setsourceUrl] = useState("");
const [imageUrl, setimageUrl] = useState("");
const [isPublished, setisPublished] = useState("true");
const [price, setprice] = useState("");
const [tags, settags] = useState([]);
const history = useHistory();
async function login() {
let item = {
dishName,
category,
author,
ingredients,
cookingTime,
sourceUrl,
imageUrl,
isPublished,
price,
tags,
};
await fetch("http://localhost:1234/api/courses", {
method: "POST",
body: JSON.stringify(item),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
});
history.push("/addCourse");
// window.location.reload();
}
return (
<div className="col-sm-6" style={{ textAlign: "center" }}>
<h1 className="bigBar">Create new recipe</h1>
<input
type="text"
onChange={e => setdishName(e.target.value)}
className="form-control"
placeholder="dishName"
/>
<br />
<input
type="text"
onChange={e => setcategory(e.target.value)}
className="form-control"
placeholder="cathegory"
/>
<br />
<input
type="text"
onChange={e => setauthor(e.target.value)}
className="form-control"
placeholder="author"
/>
<br />
<input
type="text"
onChange={e => setingredients(e.target.value)}
className="form-control"
placeholder='{"quantity": int, "unit": "", "description": ""}'
/>
<br />
<input
type="text"
onChange={e => setcookingTime(e.target.value)}
className="form-control"
placeholder="cooking time"
/>
<br />
<input
type="text"
onChange={e => setsourceUrl(e.target.value)}
className="form-control"
placeholder="source url"
/>
<br />
<input
type="text"
onChange={e => setimageUrl(e.target.value)}
className="form-control"
placeholder="image url"
/>
<br />
<input
type="text"
onChange={e => setisPublished(e.target.value)}
className="form-control"
placeholder="publish status (dafault: true)"
/>
<br />
<input
type="text"
onChange={e => setprice(e.target.value)}
className="form-control"
placeholder="price"
/>
<br />
<input
type="text"
onChange={e => settags(e.target.value)}
className="form-control"
placeholder="tags"
/>
<br />
<button onClick={login} className="btn btn-primary">
Sign up
</button>
</div>
);
}
当我发送数据时,我没有收到任何错误。当我单击在 MongoDB 中展开其元素时,或者在标签的情况下,它甚至没有出现在 MongoDB 中时,只有一组成分是空的。
你能告诉我如何解决这个问题,或者是我做错了什么吗?我搜索了很多答案,但 2 小时后我发现没有任何用处。
编辑:我正在为新课程添加我的 REST API 发布方法:
router.post("/", async (req, res) => {
const { error } = validateCourse(req.body);
if (error)
// 400 Bad request
return res.status(400).send(error.details[0].message);
let course = new Course(
_.pick(req.body, [
`dishName`,
`category`,
`author`,
`ingredients`,
`cookingTime`,
`sourceUrl`,
`imageUrl`,
`isPublished`,
`price`,
// `tags`,
])
);
以及新课程的架构:
const mongoose = require(`mongoose`);
const Joi = require(`joi`);
function validateCourse(body) {
const schema = Joi.object({
dishName: Joi.string().min(3).required(),
category: Joi.string().min(3).required(),
author: Joi.string().min(3).required(),
ingredients: Joi.required(),
cookingTime: Joi.number().min(0).required(),
sourceUrl: Joi.string().required(),
imageUrl: Joi.string().required(),
isPublished: Joi.boolean().required(),
price: Joi.number().min(0).required(),
tags: Joi.required(),
date: Joi.allow(),
});
return schema.validate(body);
}
const Course = mongoose.model(
`Course`,
new mongoose.Schema({
dishName: { type: String, required: true, minLength: 3, maxLength: 255 },
category: {
type: String,
required: true,
lowercase: true,
trim: true,
dishType: [
"carrot",
"broccoli",
"asparagus",
"cauliflower",
"corn",
"cucumber",
"green pepper",
"lettuce",
"mushrooms",
"onion",
"potato",
"pumpkin",
"red pepper",
"tomato",
"beetroot",
"brussel sprouts",
"peas",
"zucchini",
"radish",
"sweet potato",
"artichoke",
"leek",
"cabbage",
"celery",
"chili",
"garlic",
"basil",
"coriander",
"parsley",
"dill",
"rosemary",
"oregano",
"cinnamon",
"saffron",
"green bean",
"bean",
"chickpea",
"lentil",
"apple",
"apricot",
"avocado",
"banana",
"blackberry",
"blackcurrant",
"blueberry",
"boysenberry",
"cherry",
"coconut",
"fig",
"grape",
"grapefruit",
"kiwifruit",
"lemon",
"lime",
"lychee",
"mandarin",
"mango",
"melon",
"nectarine",
"orange",
"papaya",
"passion fruit",
"peach",
"pear",
"pineapple",
"plum",
"pomegranate",
"quince",
"raspberry",
"strawberry",
"watermelon",
"salad",
"pizza",
"pasta",
"popcorn",
"lobster",
"steak",
"bbq",
"pudding",
"hamburger",
"pie",
"cake",
"sausage",
"Tacos",
"Kebab",
"poutine",
"seafood",
"chips",
"fries",
"masala",
"paella",
"som tam",
"chicken",
"toast",
"marzipan",
"tofu",
"Ketchup",
"hummus",
"chili",
"maple syrup",
"parma ham",
"fajitas",
"champ",
"lasagna",
"poke",
"chocolate",
"croissant",
"arepas",
"bunny chow",
"pierogi",
"donuts",
"rendang",
"sushi",
"ice cream",
"duck",
"curry",
"beef",
"goat",
"lamb",
"turkey",
"pork",
"fish",
"crab",
"bacon",
"ham",
"pepperoni",
"salami",
"ribs",
"other",
],
},
author: String,
ingredients: [
{
quantity: Number,
unit: String,
description: String,
},
],
cookingTime: { type: Number, required: true },
sourceUrl: String,
imageUrl: String,
date: { type: Date, default: Date.now },
isPublished: { type: Boolean, default: true },
price: {
type: Number,
required: function () {
return this.isPublished;
},
},
tags: {
type: Array,
validate: {
validator: function (v) {
return v && v.length > 0;
},
message: `A course should have at least one tag.`,
},
},
})
);
exports.Course = Course;
exports.validateCourse = validateCourse;
解决方案
您将ingredients
状态设置为字符串,因此您基本上是“字符串化”一个字符串,这将导致JSON SyntaxError
. 如果要以这种方式发送数组,则必须指定数组括号[
并]
使其成为有效数组。
要解决它,只需更改:
<input
type="text"
onChange={e => setingredients(e.target.value)}
className="form-control"
placeholder='{"quantity": int, "unit": "", "description": ""}'
/>
您需要将其更改为:
<input
type="text"
//parse the string input
onChange={e => setingredients(JSON.parse(e.target.value))}
className="form-control"
//notice the array bracket '[' and ']'
placeholder='[{"quantity": int, "unit": "", "description": ""}, {"quantity": int, "unit": "", "description": ""}]'
/>
推荐阅读
- java - 将参数添加到 HTTPRequest 标头
- php - 如何从 table1 中选择还没有付款条目的记录?
- java - 蛇游戏 - 蛇建造但不移动,坐标不更新,尽管从教程中逐字写入
- python - 我无法使用请求登录 Instagram
- amazon-web-services - AWS SAM CodePipelines 是否每次提交都进行整个重建?
- mqtt - MQTT TLS 连接 Python --- Vb.net
- ios - NSNull boolValue 获取崩溃目标 c
- python - Python Beautiful Soup 网页抓取?
- sql - SQL Server 中的行号和分区依据
- laravel - Laravel Faker 如何获取用户名的最小和最大长度