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
相关产品推荐
相关产品推荐

