Skip to content

Commit a394dcf

Browse files
fix(not-found): 改 Server Component 修 Server Action 路径下 useTranslations 崩溃
爬虫向 / POST 时 Next 走 Server Action 路径,未匹配到 action 后渲染 not-found.tsx 不经过 root layout,NextIntlClientProvider 不在 React 树里, useTranslations 抛 "No intl context" 直接 500 上报 Sentry。 改用 next-intl/server 的 getTranslations,绕开 client provider 依赖。 umami 埋点拆到 not-found-tracker.tsx 作为 client 子组件挂载。 Sentry: SENTRY-BOLE-NOTEBOOK-2
1 parent 5c71a81 commit a394dcf

2 files changed

Lines changed: 31 additions & 17 deletions

File tree

app/not-found-tracker.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
import { usePathname } from "next/navigation";
5+
6+
// 从 not-found.tsx 拆出来的 umami 404 埋点。
7+
// 拆分原因:not-found.tsx 必须保持 Server Component(见同目录 not-found.tsx 注释),
8+
// useEffect / usePathname / window.umami 只能在 client。
9+
export default function NotFoundTracker() {
10+
const pathname = usePathname();
11+
12+
useEffect(() => {
13+
if (window.umami) {
14+
window.umami.track("error_404", {
15+
path: pathname,
16+
referrer: document.referrer || "direct",
17+
});
18+
}
19+
}, [pathname]);
20+
21+
return null;
22+
}

app/not-found.tsx

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,14 @@
1-
"use client";
2-
31
import Link from "next/link";
4-
import { useEffect } from "react";
5-
import { usePathname } from "next/navigation";
6-
import { useTranslations } from "next-intl";
2+
import { getTranslations } from "next-intl/server";
73
import { Button } from "@/app/components/ui/button";
4+
import NotFoundTracker from "./not-found-tracker";
85

9-
export default function NotFound() {
10-
const pathname = usePathname();
11-
const t = useTranslations("notFound");
12-
13-
useEffect(() => {
14-
if (window.umami) {
15-
window.umami.track("error_404", {
16-
path: pathname,
17-
referrer: document.referrer || "direct",
18-
});
19-
}
20-
}, [pathname]);
6+
// 必须是 Server Component:爬虫向 / 发 POST 时 Next 走 Server Action 路径,
7+
// not-found 渲染不经过 layout,NextIntlClientProvider 不在树里,
8+
// useTranslations 会抛 "No intl context"。getTranslations 走 server,
9+
// 直接读 i18n/request.ts,没有 provider 依赖。
10+
export default async function NotFound() {
11+
const t = await getTranslations("notFound");
2112

2213
return (
2314
<div className="flex h-screen w-full flex-col items-center justify-center bg-background text-foreground">
@@ -32,6 +23,7 @@ export default function NotFound() {
3223
<Link href="/">{t("cta")}</Link>
3324
</Button>
3425
</div>
26+
<NotFoundTracker />
3527
</div>
3628
);
3729
}

0 commit comments

Comments
 (0)