У меня есть следующий компонент
import React, { Component } from "react";
import axios from "axios";
import swal from "sweetalert";
import AuthService from "../../Auth/AuthService";
import withAuth from "../../Auth/withAuth";
const Auth = new AuthService();
class Create extends Component {
constructor() {
super();
this.state = {
title: "",
description: "",
reference: "",
images: [],
price: "",
year: "",
categoryName: "",
categorys: [],
sold: false,
titleErr: "",
descriptionErr: "",
referenceErr: "",
imagesErr: "",
priceErr: "",
yearErr: "",
categoryErr: ""
};
}
validate = () => {
let titleErr = "";
let descriptionErr = "";
let referenceErr = "";
let imagesErr = "";
let priceErr = "";
let yearErr = "";
let categoryNameErr = "";
// Title validation
if (!this.state.title) {
titleErr = "Please enter a title";
}
// Description validation
if (!this.state.description) {
descriptionErr = "Please enter a description";
}
// Reference validation
if (!this.state.reference) {
referenceErr = "Please enter a reference";
}
// Images validation
if (!this.state.images.length) {
imagesErr = "You must have at least one image";
}
// Price validation
if (!this.state.price) {
priceErr = "Please enter a price";
}
// Year validation
if (!this.state.year) {
yearErr = "Please enter a year";
}
// Category validation
if (!this.state.categoryName) {
categoryNameErr = "Please enter a category";
}
// Render validations
if (
titleErr ||
descriptionErr ||
referenceErr ||
imagesErr ||
priceErr ||
yearErr ||
categoryNameErr
) {
this.setState({
titleErr,
descriptionErr,
referenceErr,
imagesErr,
priceErr,
yearErr,
categoryNameErr
});
return false;
}
return true;
};
componentDidMount() {
axios
.get("/api/category")
.then(res => this.setState({ categorys: res.data }))
.catch(error => {
console.log(error);
});
}
onTitleChange(event) {
this.setState({ title: event.target.value });
}
onDescriptionChange(event) {
this.setState({ description: event.target.value });
}
onReferenceChange(event) {
this.setState({ reference: event.target.value });
}
onImagesChange(event) {
this.setState({ images: event.target.value });
}
onPriceChange(event) {
this.setState({ price: event.target.value });
}
onYearChange(event) {
this.setState({ year: event.target.value });
}
onCategoryNameChange(event) {
this.setState({ categoryName: event.target.value });
}
onSoldChange(event) {
this.setState({ sold: event.target.value });
}
onSubmit = e => {
e.preventDefault();
const isValid = this.validate();
const {
title,
description,
reference,
images,
price,
year,
categoryName,
sold
} = this.state;
let config = {
headers: {
"Content-Type": "multipart/form-data",
Authorization: "bearer " + Auth.getToken()
}
};
var formData = new FormData();
formData.append("title", title);
formData.append("description", description);
formData.append("reference", reference);
formData.append("price", price);
formData.append("images", images);
formData.append("year", year);
formData.append("categoryName", categoryName);
formData.append("sold", sold);
for (let i = 0; i < images.length; i++) {
formData.append("images", images[i]);
}
if (isValid) {
axios
.post("/api/collections/create", formData, config)
.then(function(response) {
swal({
title: "Success",
text: "You have created a collection",
icon: "success",
button: "OK"
});
this.props.history.push("/dashboard");
console.log(response);
})
.catch(function(response) {
swal({
title: "Error",
text: `${response}`,
icon: "error",
button: "Try again"
});
});
}
};
render() {
const {
title,
description,
reference,
images,
price,
year,
categoryName,
sold
} = this.state;
return (
<>
<div className='block md:flex md:flex-column h-full'>
<div className='p-12 w-full text-center text-gray-800'>
<h1 className='title mb-10'>Create a collection</h1>
<form
className='w-full m-auto max-w-lg'
encType='multipart/form-data'
onSubmit={this.onSubmit}
>
<div className='flex flex-wrap mb-4'>
<label htmlFor='title'>Title:</label>
<input
type='text'
name='title'
value={title}
onChange={this.onTitleChange.bind(this)}
placeholder='Title'
/>
<p className='mt-2 text-red-500 text-xs'>
{this.state.titleErr}
</p>
</div>
<div className='flex flex-wrap'>
<label htmlFor='description'>Description:</label>
<textarea
type='text'
name='description'
className='h-64'
value={description}
onChange={this.onDescriptionChange.bind(this)}
placeholder='Content'
></textarea>
<p className='mb-4 text-red-500 text-xs'>
{this.state.descriptionErr}
</p>
</div>
<div className='flex flex-wrap mb-4'>
<label htmlFor='reference'>Reference:</label>
<input
type='text'
name='reference'
value={reference}
onChange={this.onReferenceChange.bind(this)}
placeholder='reference'
/>
<p className='mt-2 text-red-500 text-xs'>
{this.state.referenceErr}
</p>
</div>
<div className='flex flex-wrap mb-4'>
<label htmlFor='images'>images:</label>
<input
type='file'
multiple
name='images'
value={images}
accept='image/*'
onChange={this.onImagesChange.bind(this)}
></input>
<p className='mt-2 text-red-500 text-xs'>
{this.state.imagesErr}
</p>
</div>
<div className='flex flex-wrap mb-4'>
<label htmlFor='price'>Price:</label>
<input
type='number'
name='price'
value={price}
onChange={this.onPriceChange.bind(this)}
placeholder='price'
/>
<p className='mt-2 text-red-500 text-xs'>
{this.state.priceErr}
</p>
</div>
<div className='flex flex-wrap mb-4'>
<label htmlFor='year'>Year:</label>
<input
type='number'
name='year'
value={year}
onChange={this.onYearChange.bind(this)}
placeholder='Year'
/>
<p className='mt-2 text-red-500 text-xs'>
{this.state.yearErr}
</p>
</div>
<div className='flex flex-col mb-4'>
<label htmlFor='categoryName'>Category</label>
<div className='relative'>
<select
name='categoryName'
value={categoryName}
onChange={this.onCategoryNameChange.bind(this)}
>
<option>N/A</option>
{this.state.categorys.map(category => (
<option key={category._id} value={category.name}>
{category.name}
</option>
))}
</select>
<div className='pointer-events-none absolute inset-y-0 right-0 flex items-center px-2'>
<svg
className='fill-current h-4 w-4'
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 20 20'
>
<path d='M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z' />
</svg>
</div>
</div>
</div>
<div className='flex flex-col mb-2'>
<label htmlFor='sold'>Sold?</label>
<div className='relative'>
<select
name='sold'
value={sold}
onChange={this.onSoldChange.bind(this)}
>
<option value='false'>No</option>
<option value='true'>Yes</option>
</select>
<div className='pointer-events-none absolute inset-y-0 right-0 flex items-center px-2'>
<svg
className='fill-current h-4 w-4'
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 20 20'
>
<path d='M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z' />
</svg>
</div>
</div>
</div>
<div className='flex'>
<button type='submit' className='btn w-full'>
Submit
</button>
</div>
</form>
</div>
</div>
</>
);
}
}
export default withAuth(Create);
Я пытаюсь сохранить все изображения в виде массива, чтобы я мог сохранить имя файла и местоположение s3.
С точки зрения экспресс-я имеюследующее
/* POST create a collection */
module.exports.createCollection = [
...validations,
(req, res) => {
// Get validation errors from the request
const errors = validationResult(req);
// Return the errors
if (!errors.isEmpty()) {
return res.status(422).json({ error: errors.array() });
}
Collections.findOne({ _id: req.body.id })
.then(function(collection) {
return Collections.create({
title: req.body.title,
description: req.body.description,
reference: req.body.reference,
images: req.files.map(({ originalname, location }) => ({
originalname,
location
})),
price: req.body.price,
year: req.body.year,
categoryName: req.body.categoryName,
sold: req.body.sold
});
})
.then(
function(collection) {
res.status(201).json(collection);
console.log("Successfully uploaded " + req.files.length + " files!");
},
function(error) {
console.error(error);
res.status(500).send(error);
}
);
}
];
Когда я проверяю это в почтальоне, запрос работает и я получаю желаемый результат, однако реагирую не так сильно.
Ошибка, которую я получаю Error: Request failed with status code 422
.
Это ожидаемый результат в почтальоне.
Изображения загружаются при создании записей в почтальоне, поэтому проблема здесь, похоже, связана с React.
Как мне поступить в реакции?