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

Next.js 13.x中服务器组件从错误边界恢复重渲染问题

问题:Next.js 错误边界触发后无法恢复服务器组件渲染

场景:根路由page.tsx为服务器组件,从REST Countries API获取并展示国家列表;search-bar.tsx是客户端组件,提供搜索筛选功能。当搜索不存在的国家导致API返回404时,触发error.tsx错误边界,但无法恢复并重渲染page.tsx的服务器组件——虽然重置路径到根路由时API请求已触发,但UI仍停留在错误界面。

原因分析

你在error.tsx中直接覆盖了Next.js传入的内置reset回调函数,这个函数是Next.js专门用来恢复错误边界、重新渲染出错的服务器组件的核心逻辑。自定义的reset只执行了路由跳转和刷新,跳过了错误边界的恢复流程,导致UI无法回到正常状态。

解决方案

方案1:正确使用Error组件的内置reset函数

保留Next.js传入的reset函数,结合路由操作完成恢复:

修改error.tsx代码:

"use client";

import { useRouter } from "next/navigation";
import { useEffect } from "react";

const Error = ({ error, reset }: { error: Error, reset: () => void }) => {
  const router = useRouter();

  const handleReset = async () => {
    // 清空搜索参数,回到根路由
    router.push("/");
    // 调用内置reset,触发服务器组件重新渲染
    await reset();
    // 强制刷新路由,确保最新数据展示
    router.refresh();
  };

  useEffect(() => {
    console.error(error);
  }, [error]);

  return (
    <div>
      <h2 className="text-red-400">出错了!</h2>
      <button onClick={handleReset}>回到国家列表</button>
    </div>
  );
};

export default Error;

方案2:在服务器组件中处理404,避免触发错误边界

更友好的方式是在API请求时捕获404,返回空数组而非抛出错误,这样不会进入错误边界,直接在页面中展示无结果提示:

  1. 修改page.tsx中的getCountryByName函数:
const getCountryByName = async (countryName: string) => {
  const res = await fetch(`https://restcountries.com/v3.1/name/${countryName}`);
  if (!res.ok) {
    // 针对404返回空数组,不抛出错误
    if (res.status === 404) {
      return [];
    }
    // 其他错误仍抛出,触发错误边界
    throw new Error("Failed to fetch country data");
  }
  return res.json();
};
  1. 在Home组件中添加无结果判断:
export default async function Home({ params, searchParams }: { params: Params, searchParams: SearchParams }) {
  const countries: Array<any> = searchParams.search ? await getCountryByName(searchParams.search as string) : await getCountriesData();
  
  return (
    <main className="flex flex-col gap-2 overflow-x-hidden">
      <header>
        <Navbar />
      </header>
      <div className="flex justify-between p-2 md:p-4">
        <SearchBar />
        <Select />
      </div>
      <div className="flex flex-wrap justify-between gap-4 p-2 md:p-4">
        {countries.length === 0 && searchParams.search ? (
          <p className="w-full text-center text-gray-500">未找到匹配的国家</p>
        ) : (
          <Countries countries={countries} />
        )}
      </div>
    </main>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:39:59