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

Next.js 13 App Router中自定义Error页面为何无法处理Fetch API错误?

解决Next.js App Router自定义error.tsx无法捕获API路由Fetch错误的问题

问题原因

你的error.tsx负责捕获所在目录(app/[lang]/)及其子目录下组件渲染时的错误,但src/api/categories/index.ts是独立的服务端API路由,它的错误不会直接触发页面的error.tsx:

  1. API路由的未处理错误会直接返回Next.js默认错误响应,而非传递给页面组件
  2. 页面组件调用API时,若未主动处理错误并抛出,error.tsx无法感知到错误

解决方案步骤

1. 先处理API路由的错误,返回规范响应

在src/api/categories/index.ts中,用try/catch包裹Fetch调用,主动返回带错误状态码的JSON响应,避免未处理错误导致默认错误页:

export async function GET() {
  try {
    const res = await fetch("你的外部API地址");
    if (!res.ok) {
      throw new Error(`外部API请求失败: ${res.status}`);
    }
    const data = await res.json();
    return Response.json(data);
  } catch (error) {
    // 返回标准错误响应,而非让错误向上抛出
    return Response.json(
      { message: "获取分类数据失败" },
      { status: error instanceof Error ? 500 : 400 }
    );
  }
}

2. 在页面组件中主动捕获API响应错误并抛出

以app/[lang]/page.tsx(服务端组件)为例,调用API后检查响应状态,手动抛出错误,让同级的error.tsx捕获:

export async function generateStaticParams() {
  // 生成静态路由参数,根据你的业务调整
  return [{ lang: "en" }, { lang: "zh-CN" }];
}

export default async function Page({ params }: { params: { lang: string } }) {
  try {
    const res = await fetch(`/api/categories`, {
      next: { revalidate: 86400 } // SSG缓存配置
    });

    // 检查API响应状态,主动抛出错误
    if (!res.ok) {
      const errorData = await res.json();
      throw new Error(errorData.message || `请求失败: ${res.status}`);
    }

    const categories = await res.json();
    return <div>{/* 渲染分类内容 */}</div>;
  } catch (error) {
    // 重新抛出错误,确保错误冒泡到error.tsx
    throw error;
  }
}

3. 客户端组件调用API的错误处理(若适用)

如果是客户端组件调用API,需在组件内捕获错误后主动抛出:

"use client";

import { useEffect, useState } from "react";

export default function CategoriesClient() {
  const [categories, setCategories] = useState<any[]>([]);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch("/api/categories");
        if (!res.ok) throw new Error(`请求失败: ${res.status}`);
        const data = await res.json();
        setCategories(data);
      } catch (err) {
        setError(err as Error);
      }
    };
    fetchData();
  }, []);

  // 抛出错误,让error.tsx捕获
  if (error) throw error;

  return <div>{/* 渲染分类内容 */}</div>;
}

关键注意事项

  • 不要将error.tsx放到src/api/目录下,API路由的错误处理是在内部返回响应,页面错误由app/目录下的error.tsx负责
  • error.tsx仅捕获组件渲染阶段的错误,必须确保错误在页面/组件层级被抛出,才能触发自定义错误页

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 00:07:45