Я пытаюсь вставить некоторые данные в базу данных с помощью POST-запроса выборки API к маршруту API Next.js, но я получаю следующие два сообщения об ошибках в консоли браузера:
api/addCompany/addCompany:1 Не удалось загрузить ресурс: сервер ответил со статусом 500 (внутренняя ошибка сервера), регистр:1
Uncaught (в обещании) SyntaxError: Неожиданный токен < в JSON в позиции 0
Это папки моего проекта (актуально из-за системы маршрутизации Next.js)
Это компонент, в котором я выполняю запрос API-интерфейса на выборку (пожалуйста, не осуждайте мои плохие навыки работы с Typescript, я новичок в этом, все еще не найдя подходящий тип события):
import styles from '../styles/Register.module.css'
import { NextPage } from "next"
import { prisma } from '../prisma/prisma_client';
import { Prisma } from '@prisma/client';
import { useSession } from "next-auth/react"
const Register: NextPage = () => {
const createCompany: any = async (event: any) => {
event.preventDefault()
const company: Prisma.CompanyCreateInput = {
companyName: event.target.companyName.value,
gender: event.target.gender.value,
firstName: event.target.firstName.value,
lastName: event.target.lastName.value,
street: event.target.street.value,
houseNumber: parseInt(event.target.houseNumber.value),
postcode: parseInt(event.target.postcode.value),
city: event.target.city.value,
country: event.target.country.value,
countryCode: event.target.countryCode.value,
callNumber: parseInt(event.target.callNumber.value),
emailAddress: event.target.emailAddress.value,
website: event.target.website.value,
socials: {},
companyUser: {
connect: { id: 'cl0y4y8xo0021mwtcmwlqfif6' }
}
}
const companyJSON = JSON.stringify(company)
const endpoint = '/api/addCompany/addCompany'
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: companyJSON,
}
const response = await fetch(endpoint, options)
const data = await response.json()
console.info(data)
}
return (
<form onSubmit = {createCompany} className = {styles.form} id = "signupForm" noValidate>
<h2>Company Information</h2>
<div className = "fieldWrapper">
<input type = "text" id = "companyName" name = "companyName" placeholder = " " />
<label htmlFor = "companyName">Company Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" list = "genders" id = "gender" name = "gender" placeholder = " " />
<label htmlFor = "gender">Gender<span>*</span></label>
<div className='errorMessage'></div>
<datalist id = "genders">
<option>Female</option>
<option>Male</option>
</datalist>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "firstName" name = "firstName" placeholder = " " />
<label htmlFor = "firstName">First Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "lastName" name = "lastName" placeholder = " " />
<label htmlFor = "lastName">Last Name<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "street" name = "street" placeholder = " " />
<label htmlFor = "street">Street<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "number" id = "houseNumber" name = "houseNumber" placeholder = " " />
<label htmlFor = "houseNumber">House Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "number" id = "postcode" name = "postcode" placeholder = " " />
<label htmlFor = "postcode">Postcode<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "city" name = "city" placeholder = " " />
<label htmlFor = "city">City<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "country" name = "country" placeholder = " " />
<label htmlFor = "country">Country<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "countryCode" name = "countryCode" placeholder = " " />
<label htmlFor = "countryCode">Country Code<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "number" id = "callNumber" name = "callNumber" placeholder = " " />
<label htmlFor = "callNumber">Call Number<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "email" id = "emailAddress" name = "emailAddress" placeholder = " " />
<label htmlFor = "emailAddress">Email Address<span>*</span></label>
<div className='errorMessage'></div>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "website" name = "website" placeholder = " " />
<label htmlFor = "website">Website</label>
</div>
<div className = "fieldWrapper">
<input type = "text" id = "socials" name = "socials" placeholder = " " />
<label htmlFor = "socials">Socials</label>
</div>
<div className = "fieldWrapper">
<button type = "submit">Save</button>
</div>
</form>
)
}
export default Register
И это код файла addCompany, который служит маршрутом API Next.js для моего запроса API выборки:
import { Prisma } from '@prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body} = req;
const companyData: Prisma.CompanyCreateInput = JSON.parse(body);
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
Я ценю любую помощь. Спасибо.
я пытался закомментировать
const data = await response.json() console.info(data)
в компоненте регистрации, поэтому ошибка «Uncaught (in promise) SyntaxError: Unexpected token <in JSON at position 0» исчезла, но это вообще не решение проблемы.
Я также пытался настроить маршрут моего запроса на выборку для любого возможного варианта, потому что я не был уверен, как именно Next.js выполняет его автозаполнение, например, я пробовал: «/api/addCompany/addCompany.ts» и так далее.
Я ожидаю, что проблема будет чем-то небольшим, я надеюсь, что это не опечатка. Еще раз спасибо.
PS: я также проверял похожие сообщения по этому вопросу, но не смог найти решение своей проблемы.
Нет необходимости повторно анализировать данные тела в конечной точке API, поскольку ПО промежуточного слоя Next.js уже преобразует эти данные в объект:
API routes provide built in middlewares which parse the incoming request (
req
). Those middlewares are:
req.cookies
- An object containing the cookies sent by the request. Defaults to{}
req.query
- An object containing the query string. Defaults to{}
req.body
- An object containing the body parsed bycontent-type
, ornull
if no body was sent
что-то вроде ниже должно работать:
import { Prisma } from '@prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../../prisma/prisma_client';
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const {body: companyData} = req;
//const companyData: Prisma.CompanyCreateInput = JSON.parse(body);<- No need to reparse the data here
const addCompany = await prisma.company.create({
data: companyData
})
res.status(200).json(addCompany);
}
export default handler
Благодаря этому ответу здесь за разъяснение.
@JakobBasshunterWidmann на самом деле вы правы в том, что Prisma принимает только объекты javascript в data
, я отредактировал свой ответ для правильного разъяснения проблемы.
Мне нужно разобрать его, потому что операции создания prisma не принимают JSON, как указано в их документации: prisma.io/docs/concepts/components/prisma-client/crud#create