语法错误:submitComment 处 JSON 输入意外结束

问题描述 投票:0回答:1

我正在使用 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,在这个版本中发生了很多变化,所以我可能有错的地方

javascript graphql next.js13
1个回答
0
投票

问题是在尝试读取 route.js 中的 req.body.namereq.body.email 等时出现的,这些内容在新版本中未定义。
要从身体读取数据,您需要执行类似的操作

const body = await req.json();
console.log(body.name); // change name with email, comment, slug
© www.soinside.com 2019 - 2024. All rights reserved.