我正在使用 YouTube 视频创建一个项目,一个一年前的项目,决定使用 NextJS v13.4 来做,但是出了问题,我在 API 中遇到了错误,该 API 负责将从网站收到的评论发送到CMS。
单击按钮后,我收到如下错误:
POST http://localhost:3000/api 500 (Internal Server Error)
服务器控制台也出现错误:
- error ClientError: variable 'name' must be defined: {"response":{"errors":[{"message":"variable 'name' must be defined"}],"data":null,"extensions":{"requestId":"clhq6vo5j0es00aw2sirvp7y0"},"status":400,"headers":{}},"request":{"query":"\n mutation CreateComment($name: String!, $email: String!, $comment: String!, $slug: String!) {\n createComment(data: {name: $name, email: $email, comment: $comment, post: {connect: {slug: $slug}}}) { id }\n }\n ","variables":{}}}
at makeRequest (webpack-internal:///(sc_server)/./node_modules/graphql-request/build/cjs/index.js:313:15)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async POST (webpack-internal:///(sc_server)/./app/api/route.js:19:20)
at async eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:244:37) {
response: {
errors: [ [Object] ],
data: null,
extensions: { requestId: 'clhq6vo5j0es00aw2sirvp7y0' },
status: 400,
headers: Headers { [Symbol(map)]: [Object: null prototype] }
},
request: {
query: '\n' +
' mutation CreateComment($name: String!, $email: String!, $comment: String!, $slug: String!) {\n' +
' createComment(data: {name: $name, email: $email, comment: $comment, post: {connect: {slug: $slug}}}) { id }\n' +
' }\n' +
' ',
variables: {
name: undefined,
email: undefined,
comment: undefined,
slug: undefined
}
}
}
./services/index.js
export const submitComment = async (obj) => {
const result = await fetch('/api', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(obj),
});
return result.json();
};
./app/api/route.js
import { GraphQLClient, gql } from 'graphql-request';
const graphqlAPI = process.env.NEXT_PUBLIC_GRAPHCMS_ENDPOINT;
const graphcmsToken = process.env.GRAPHCMS_TOKEN;
export async function POST(req, res) {
const client = new GraphQLClient(graphqlAPI, {
headers: {
authorization: `Bearer ${graphcmsToken}`,
},
});
const query = gql`
mutation CreateComment($name: String!, $email: String!, $comment: String!, $slug: String!) {
createComment(data: {name: $name, email: $email, comment: $comment, post: {connect: {slug: $slug}}}) { id }
}
`;
const result = await client.request(query, {
name: req.body.name,
email: req.body.email,
comment: req.body.comment,
slug: req.body.slug,
});
return res.status(200).send(result);
}
./components/CommentsForm.js
'use client';
import { useEffect, useRef, useState } from 'react';
import { submitComment } from '@/services';
const CommentsForm = ({ slug }) => {
const [error, setError] = useState(false);
const [showSuccessMessage, setShowSuccessMessage] = useState(false);
const commentEL = useRef();
const nameEl = useRef();
const emailEl = useRef();
const storeDataEl = useRef();
useEffect(() => {
nameEl.current.value = window.localStorage.getItem('name');
emailEl.current.value = window.localStorage.getItem('email');
}, []);
const handleCommentSubmission = () => {
setError(false);
const { value: comment } = commentEL.current;
const { value: name } = nameEl.current;
const { value: email } = emailEl.current;
const { checked: storeData } = storeDataEl.current;
if (!comment || !name || !email) {
setError(true);
return;
}
if (storeData) {
window.localStorage.setItem('name', name);
window.localStorage.setItem('email', email);
} else {
window.localStorage.removeItem('name');
window.localStorage.removeItem('email');
}
const commentObj = { name, email, comment, slug };
submitComment(commentObj).then((res) => {
setShowSuccessMessage(true);
setTimeout(() => {
setShowSuccessMessage(false);
}, 3000);
});
};
return (
<div className='bg-white shadow-lg rounded-lg p-8 pb-12 mb-8'>
<h3 className='text-xl mb-8 font-semibold border-b pb-4'>
Leave a Reply
</h3>
<div className='grid grid-cols-1 gap-4 mb-4'>
<textarea
ref={commentEL}
className='p-4 outline-none w-full rounded-lg focus:ring-2 focus:ring-gray-200 bg-gray-100 text-gray-700'
placeholder='Comment'
name='comment'
/>
</div>
<div className='grid grid-cols-1 lg:grid-cols-2 gap-4 mb-4'>
<input
ref={nameEl}
type='text'
className='py-2 px-4 outline-none w-full rounded-lg focus:ring-2 focus:ring-gray-200 bg-gray-100 text-gray-700'
placeholder='Name'
name='name'
/>
<input
ref={emailEl}
type='text'
className='py-2 px-4 outline-none w-full rounded-lg focus:ring-2 focus:ring-gray-200 bg-gray-100 text-gray-700'
placeholder='Email'
name='email'
/>
</div>
<div className='grid grid-cols-1 gap-4 mb-4'>
<div>
<input
ref={storeDataEl}
type='checkbox'
id='storeData'
name='storeData'
value={true}
/>
<label
className='text-gray-500 cursor-pointer ml-2'
htmlFor='storeData'>
Save my email address and name for the next comments.
</label>
</div>
</div>
{error && (
<p className='text-xs text-red-500'>All fields are required.</p>
)}
<div className='mt-8'>
<button
type='button'
onClick={handleCommentSubmission}
className='transition duration-300 hover:bg-indigo-900 inline-block bg-pink-600 text-lg rounded-full text-white px-8 py-3 cursor-pointer'>
Post comment
</button>
{showSuccessMessage && (
<span className='text-xl float-right font-semibold mt-3 text-green-500'>
Comment submitted for review
</span>
)}
</div>
</div>
);
};
export default CommentsForm;
我还在学习NextJS v13,在这个版本中发生了很多变化,所以我可能有错的地方
问题是在尝试读取 route.js 中的 req.body.name、req.body.email 等时出现的,这些内容在新版本中未定义。
要从身体读取数据,您需要执行类似的操作
const body = await req.json();
console.log(body.name); // change name with email, comment, slug