#javascript #reactjs #next.js
Вопрос:
Я создаю страницу загрузки продукта для сайта электронной коммерции с помощью React/NextJS. Публикация формы работала нормально, просто используя action=’/admin/api/addproduct’ в элементе формы, но я изо всех сил пытаюсь добиться успеха при реализации функции для создания и отправки формы.
Вот код для формы загрузки — AddProductForm.js:
import React, {useState} from 'react';
import { useRouter } from 'next/router'
import {Form} from 'react-bootstrap'
export default function AddProductForm({ }) {
const router = useRouter()
// userInput is for adding colours.
const [userInput, setUserInput ] = useState('');
// Form State Variables
const [id, setId] = useState('')
const [name, setName] = useState('')
const [description, setDescription] = useState('')
const [gender, setGender] = useState('')
const [price, setPrice] = useState('')
const [isOnSale, setIsOnSale] = useState('')
const [discount, setDiscount] = useState('')
const [colours, setColours ] = useState([]);
const [sizes, setSizes] = useState([])
const handleAddProduct = async event => {
event.preventDefault();
const body = new FormData()
body.append("name", name);
body.append("description", description);
body.append("gender", gender);
body.append("id", id);
body.append("price", price);
body.append("isOnSale", isOnSale);
body.append("discount", discount);
colours.forEach( (colour, index) => {
body.append(`colour-${index}`, colour)
})
const response = await fetch(
"/api/addproduct",
{
body: body,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: "POST"
})
.then(response => {
alert(response['message'])
router.push("/admin/inventory")
})
.catch(error => {
console.log(error)
})
}
const handleChangeColour = (e) => {
setUserInput(e.currentTarget.value)
}
const handleRemoveColour = (e) => {
e.preventDefault();
const colourId = e.target.getAttribute("name")
setColours(colours.filter(colour => colour.id != colourId));
}
const addColour = (userInput) => {
let copy = [...colours];
setColours(copy);
copy.push({id: colours.length 1, colour: userInput});
}
const handleAddColour = (e) => {
e.preventDefault();
addColour(userInput);
setUserInput("");
}
const handleChangeSizes = (e) => {
alert("hello")
}
return (
<Form id="add-item-form" onSubmit={handleAddProduct}>
<div className="row">
<div className ="col-lg-6">
<Form.Group className="mb-3" controlId="formProductId">
<Form.Control type="text" name="formProductId" placeholder="Enter Product Id" onChange={e => setId(e.target.value)} required/>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductName">
<Form.Control name="formProductName" type="text" placeholder="Enter Product Name" onChange={e => setName(e.target.value)}required/>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductGender">
<Form.Select name="formProductGender" aria-label="Gender Select" onChange={e => setGender(e.target.value)} required>
<option>Is this male, female, or both</option>
<option value="1">Male</option>
<option value="2">Female</option>
<option value="3">Unisex</option>
</Form.Select>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductPrice" >
<Form.Control name="formProductPrice" type="number" placeholder="Enter Product Price" onChange={e => setPrice(e.target.value)} required/>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductDiscount">
<Form.Control name="formProductDiscount" type="number" placeholder="Enter Current Discount (in %)" onChange={e => setDiscount(e.target.value)} required/>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductIsOnSale">
<Form.Select name="formProductIsOnSale" aria-label="Sale Select" onChange={e => setIsOnSale(e.target.value)} required>
<option>Is this product on sale?</option>
<option value="1">Yes</option>
<option value="2">No</option>
</Form.Select>
</Form.Group>
</div>
<div className ="col-lg-6">
<Form.Group className="mb-3 " controlId="formProductDescription">
<Form.Control name="formProductDescription" type="text" placeholder="Enter Product Description" onChange={e => setDescription(e.target.value)} required/>
</Form.Group>
<Form.Group className="mb-3 " controlId="formProductSizes">
<Form.Label>Available Sizes</Form.Label>
<div className="row">
<div className="col-sm-2"></div>
<div className="col-sm-8">
<div className="row">
{['xs', 's', 'm', 'l', 'xl', 'xxl'].map(function(size, index){
return (
<div className="col" key={index}>
<Form.Check
type='checkbox'
id={`${size}-checkbox`}
name={`${size}-checkbox`}
label={`${size}`}
onChange={handleChangeSizes}
/>
</div>
)})}
</div>
</div>
<div className="col-sm-2"></div>
</div>
</Form.Group>
<Form.Group className="mb-3" controlId="formProductColours">
<div className="row">
<div className="col">
<Form.Label className="ml-5">Available Colours</Form.Label>
</div>
<div className="col">
<input value={userInput} type="text" onChange={handleChangeColour} placeholder="Enter Colour..."/>
</div>
<div className="col pb-1">
<div className="btn btn-outline-success btn-sm mb-1" onClick={handleAddColour}> </div>
</div>
</div>
{colours.map(colour => {
return (
<>
<div className="row" key={colour.id}>
<div className="col">
<div > {colour.colour} </div>
</div>
<div className="col">
<div className="col pb-1">
<div name={colour.id} class="btn btn-outline-success btn-sm mb-1" onClick={handleRemoveColour}>-</div>
</div>
</div>
</div>
<input type="hidden" name={`colour-{colour.colour}`}></input>
</>
)
})}
</Form.Group>
</div>
</div>
<button type="submit" className="btn btn-outline-success">
Add Product
</button>
</Form>
)
}
А вот код api addproduct.js
import {connectToDatabase} from '../../lib/mongodb'
async function addProduct(item){
const { db } = await connectToDatabase();
const resp = await db
.collection("stock")
.insertOne(item)
}
const post = async (req, res) => {
var colourList=[]
var sizeList=[]
Object.keys(req.body).forEach( key => {
if (key.substring(0,7) == "colour-"){
colourList.push(req.body[key])
}
if (key.substring(0,14) == "size-checkbox-"){
sizeList.push(key.substring(14))
}
})
// Extract Form Data
var newItem = JSON.stringify( {
id : req.body['id'],
name : req.body['name'],
description : req.body['description'],
gender : req.body['gender'],
starRating : null,
price : req.body['price'],
isOnSale : req.body['isOnSale'],
discount : req.body['discount'],
colours : colourList,
sizes : sizeList,
})
console.log(newItem)
// //add the stock to the db
// const resp = await addProduct(newItem)
res.status(201).send({ message: 'Item Added' })
return
};
export default (req, res) => {
req.method === "POST"
? post(req, res)
: req.method === "PUT"
? console.log("PUT")
: req.method === "DELETE"
? console.log("DELETE")
: req.method === "GET"
? console.log("GET")
: res.status(404).send("");
};
В вызове api addproduct есть консоль.войдите в журнал, чтобы распечатать новый элемент. Результат выглядит следующим образом
{"starRating":null,"colours":[],"sizes":[]}
Что также сбивает с толку, почему он выводит только эти 3 атрибута?
Если я console.log(req.body), это то, что я получаю
[Object: null prototype] {
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rnContent-Disposition: form-data; name': '"name"rn'
'rn'
'ewrn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="description"rn'
'rn'
'asdadasrn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="gender"rn'
'rn'
'1rn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="id"rn'
'rn'
'weqwern'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="price"rn'
'rn'
'323rn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="isOnSale"rn'
'rn'
'1rn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="discount"rn'
'rn'
'32rn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5rn'
'Content-Disposition: form-data; name="colour-0"rn'
'rn'
'[object Object]rn'
'------WebKitFormBoundaryrsGiVVNnm3aU1Ww5--rn'
}
Кроме того, в функции handleAddProduct «const response = ожидание выборки» я ссылаюсь на ответ в разделе». затем», но это не относится к тому же объекту ответа, объявленному ранее, и, следовательно, сообщение не отображается в предупреждении после попытки добавить элемент.
Комментарии:
1. Кажется
req.body
, что его не существует. Не могли бы вы попробовать что-нибудьconsole.log(req)
иconsole.log(res)
посмотреть, что на самом деле передается?2. Я обновил вопрос, чтобы включить результат console.log(req.body), который показывает тело, я использую const body = new FormData() для создания тела.
3. Хорошо, поэтому я думаю, что сначала вам нужно преобразовать
FormData()
объект обратно в обычный объект, чтобы он снова стал доступным. Можете ли вы попробоватьlet info = Object.fromEntries(req.body.entries())
, а затем соответствующим образом изменить другие значения