You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13页面数据获取报错求助:JSON解析异常

问题描述

我刚学Next.js,之前用非测试版且不用app目录的环境时,不用"use client"就能正常运行代码。现在想学习新版本,结果在首页展示数据时出现undefined is not valid JSON和SyntaxError: Unexpected token u in JSON at position 0错误,但直接访问localhost:3000/api/quotes能正常看到数据。

相关代码如下:

API路由代码(api/quotes/route.ts)

import { Quotes } from "@/app/models/quotes";
import { NextResponse } from "next/server";

export async function GET(request: Request) {
  const response = await fetch("https://type.fit/api/quotes");
  const quotesResponse: Quotes = await response.json();

  return NextResponse.json(quotesResponse);
}

页面代码(page.tsx)

"use client";
import { useEffect, useState } from "react";
import { Quotes } from "./models/quotes";

export default function Home() {
  const [quotes, setQuotes] = useState<Quotes>();

  useEffect(() => {
    const getQuotes = async () => {
      const response = await fetch("/api/quotes");

      const quotesResponse: Quotes = await response.json();
      setQuotes(quotesResponse);
    };

    getQuotes();
  }, []);

  return (
    <div>
      <div>{JSON.stringify(quotes)}</div>
    </div>
  );
}
解决方法

1. 先校验API响应状态

直接调用response.json()前必须确认请求成功,若API返回错误状态码(如500、404),response.json()会抛出异常,导致后续JSON解析失败。修改前端请求逻辑:

"use client";
import { useEffect, useState } from "react";
import { Quotes } from "./models/quotes";

export default function Home() {
  const [quotes, setQuotes] = useState<Quotes>();
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const getQuotes = async () => {
      try {
        const response = await fetch("/api/quotes");
        
        // 先检查响应状态是否正常
        if (!response.ok) {
          throw new Error(`请求失败:${response.status} ${response.statusText}`);
        }
        
        const quotesResponse: Quotes = await response.json();
        setQuotes(quotesResponse);
      } catch (err) {
        setError(err instanceof Error ? err.message : "未知错误");
        console.error("获取数据失败:", err);
      }
    };

    getQuotes();
  }, []);

  return (
    <div>
      {error && <div style={{color: 'red'}}>{error}</div>}
      <div>{quotes ? JSON.stringify(quotes) : "加载中..."}</div>
    </div>
  );
}

2. 验证类型定义匹配度

检查Quotes类型是否和https://type.fit/api/quotes返回的数据结构完全匹配。该接口实际返回数组类型,确保类型定义正确:

// app/models/quotes.ts
export interface Quote {
  text: string;
  author: string;
  // 其他字段根据接口实际返回补充
}

export type Quotes = Quote[];

3. 避免初始渲染时序列化undefined

初始状态下quotes为undefined,直接JSON.stringify(undefined)会返回字符串"undefined",这是触发Unexpected token u错误的原因之一。修改渲染逻辑:

<div>{quotes ? JSON.stringify(quotes) : ""}</div>

4. (推荐)改用服务器组件简化逻辑

既然用的是App Router,完全可以跳过客户端请求,直接在服务器组件中获取数据,无需"use client":

// page.tsx(无需"use client")
import { Quotes } from "./models/quotes";

export default async function Home() {
  const response = await fetch("https://type.fit/api/quotes", {
    cache: "force-cache" // 根据需求配置缓存策略
  });
  
  if (!response.ok) {
    throw new Error("获取引用数据失败");
  }
  
  const quotes: Quotes = await response.json();

  return (
    <div>
      <div>{JSON.stringify(quotes)}</div>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Jon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:32:23