如何修复 Next.js 中路由处理器返回后浏览器加载图标持续旋转的问题

酷浩吖_8039

酷浩吖_8039

2026-04-05

604人浏览

原创

如何修复 Next.js 中路由处理器返回后浏览器加载图标持续旋转的问题

在 Next.js 应用中,使用 fetch 调用 Route Handler 并执行 router.push() 后,浏览器标签页的加载图标仍持续旋转,通常是因为未显式终止客户端加载状态,导致浏览器误判导航未完成。

在 next.js 应用中,使用 `fetch` 调用 route handler 并执行 `router.push()` 后,浏览器标签页的加载图标仍持续旋转,通常是因为未显式终止客户端加载状态,导致浏览器误判导航未完成。

这个问题表面看是“UI 卡在加载态”,实则源于浏览器对 导航生命周期 的判断逻辑:当页面通过客户端导航(如 router.push)跳转时,若发起请求的组件仍处于 loading = true 状态,且该状态未被及时重置,Next.js 的客户端路由器可能无法准确标记前一个路由的“退出完成”,从而让浏览器维持挂起的加载指示器(即标签页右上角的旋转图标)。更严重的是,在 Vercel 等 Serverless 平台部署时,这种未终结的状态还可能被误判为函数长时间运行,触发超时错误(Serverless function timed out)。

关键修复点在于:无论请求成功或失败,只要服务端响应已接收,就必须立即清除加载状态。你当前的代码仅在 data.status === 200 分支中调用了 router.push("/"),但遗漏了 setLoading(false) —— 这导致即使重定向发生,loading 状态仍为 true,干扰了 Next.js 的路由状态同步机制。

以下是修正后的 handleSubmit 实现(含健壮性增强):

Browser Js
Browser Js

轻量级CDP浏览器控制,适用于AI代理。相较于内置浏览器工具,token消耗降低3‑10倍,仅在浏览时使用。

下载
const handleSubmit = async () => {
  setLoading(true);
  try {
    const res = await fetch("/api/saveRecipe", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        title,
        time,
        time_unit: timeUnit,
        serves,
        ingredients,
        instructions,
      }),
    });

    const data = await res.json();

    // ✅ 关键:无论成功或失败,响应到达后立即关闭 loading 状态
    setLoading(false);

    if (res.ok && data.status === 200) {
      router.push("/");
    } else {
      console.error("Save failed:", data.error);
      setError(true);
    }
  } catch (e) {
    setLoading(false); // ✅ 异常路径同样需重置
    console.error("Network or parsing error:", e);
    setError(true);
  }
};

此外,建议同步优化你的 Route Handler,确保始终返回明确的 HTTP 状态码和结构化响应:

// app/api/saveRecipe/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

export const dynamic = "force-dynamic";

export async function POST(req: Request) {
  const supabase = createRouteHandlerClient({ cookies });

  try {
    const body = await req.json();

    const { error } = await supabase.from("Recipes").insert(body);
    if (error) {
      console.error("Supabase insert error:", error);
      return NextResponse.json(
        { error: "Failed to save recipe", status: 500 },
        { status: 500 }
      );
    }

    // ✅ 显式返回 200 状态码(避免默认 200 但响应体不一致)
    return NextResponse.json(
      { status: 200, message: "Recipe saved successfully" },
      { status: 200 }
    );
  } catch (error) {
    console.error("Unexpected error in route handler:", error);
    return NextResponse.json(
      { error: "Internal server error", status: 500 },
      { status: 500 }
    );
  }
}

注意事项总结:

  • setLoading(false) 必须放在 try 块内、所有分支(包括 if/else 和 catch)中,确保状态终将归零;
  • 避免仅依赖 router.push 触发加载结束 —— 它是导航动作,不是状态管理指令;
  • Route Handler 返回的 status 字段应与 HTTP 状态码一致,便于前端统一判断;
  • 生产环境务必添加 console.error 日志,便于快速定位超时根源(如数据库连接阻塞、未 await 的 Promise 等)。

遵循以上实践,即可彻底解决浏览器加载图标悬停问题,并提升应用在 Serverless 环境下的稳定性与可观测性。

相关文章

路由优化大师
路由优化大师

路由优化大师是一款及简单的路由器设置管理软件,其主要功能是一键设置优化路由、屏广告、防蹭网、路由器全面检测及高级设置等,有需要的小伙伴快来保存下载体验吧!

下载

相关标签:

js

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

4626

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

1149

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

4544

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

920

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

1816

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

3305

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

4293

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

2800

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

888

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 20.8万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.8万人学习