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

Next.js 14 API获取与错误处理:如何优雅配置error.tsx并展示用户错误

Next.js 14 优雅处理数据获取错误指南

一、默认服务器组件错误提示是否合适?

An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.

这段提示在生产环境的安全性层面是合理的——它避免泄露服务器端敏感信息(如API路径、内部错误栈),但对终端用户不够友好,无法明确告知问题原因与解决方向,需要自定义错误页面优化用户体验。

二、优化错误抛出逻辑

当前代码存在可改进点:错误信息复用导致无法区分错误类型、重新抛出Error时丢失原始错误上下文、日志输出不够规范。优化后的代码如下:

// 自定义错误类,携带更多上下文信息
class FetchError extends Error {
  status?: number;
  constructor(message: string, status?: number) {
    super(message);
    this.name = 'FetchError';
    this.status = status;
    Error.captureStackTrace(this, this.constructor);
  }
}

async function fetchData() {
  try {
    const res = await fetch(APIURL, APIHeaders);

    if (!res.ok) {
      // 根据状态码生成针对性错误信息
      const errorMsg = `${errorMessage} \n状态码: ${res.status}`;
      throw new FetchError(errorMsg, res.status);
    }

    const contentType = res.headers.get('Content-Type');
    if (!contentType || !contentType.includes('application/json')) {
      throw new FetchError('接口返回格式错误,预期JSON格式');
    }

    const data = await res.json();
    return data;
  } catch (error: any) {
    // 规范日志输出,区分错误类型
    if (error instanceof FetchError) {
      console.error(`\x1b[41mURL: ${APIURL}\n错误类型: ${error.name}\n状态码: ${error.status || 'N/A'}\n错误信息: ${error.message}\x1b[0m`);
    } else {
      console.error(`\x1b[41mURL: ${APIURL}\n未知错误: ${error.message}\x1b[0m`);
    }
    
    // 重新抛出原始错误,保留上下文与错误栈
    throw error;
  }
}

关键优化点:

  • 自定义FetchError类,携带状态码等上下文,便于后续精准处理
  • 区分HTTP错误与格式错误,生成针对性错误信息
  • 重新抛出原始错误而非新建Error,避免丢失错误栈与自定义属性
  • 日志输出结构化,便于排查问题

三、配置error.tsx实现用户友好错误页面

在App Router架构中,error.tsx是页面级错误边界,可捕获路由下服务器/客户端组件的错误。你可在目标路由目录创建该文件(app/error.tsx全局生效,app/xxx/error.tsx仅作用于对应路由)。

基础配置示例

'use client'; // error.tsx 必须为客户端组件

import { useEffect } from 'react';

interface ErrorProps {
  error: Error & { digest?: string };
  reset: () => void;
}

export default function Error({ error, reset }: ErrorProps) {
  useEffect(() => {
    // 可在此处将错误上报至监控系统
    console.error('页面错误:', error);
  }, [error]);

  return (
    <div className="min-h-screen flex flex-col items-center justify-center p-4">
      <h1 className="text-2xl font-bold mb-4">哎呀,出问题了</h1>
      <p className="mb-6 max-w-md text-center">
        {process.env.NODE_ENV === 'development' ? (
          <span className="text-red-500">{error.message}</span>
        ) : (
          '服务器暂时无法处理你的请求,请稍后重试,或联系支持团队。'
        )}
      </p>
      <button
        onClick={reset}
        className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
      >
        刷新页面
      </button>
    </div>
  );
}

核心注意事项:

  • 必须标记为'use client',以支持客户端交互(如刷新按钮)
  • reset函数用于重置错误边界,允许用户尝试重新加载页面
  • 开发环境展示详细错误,生产环境显示通用提示,避免泄露敏感内容
  • 可根据自定义错误类型(如error.name === 'FetchError')展示差异化提示
  • 可添加错误上报逻辑,将错误信息同步至监控系统

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:01:20