refactor: migrate error handling to TanStack Router and add RawError type

Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
2026-02-06 20:55:44 +08:00
parent 3c4e078bdd
commit f4a5b37892
3 changed files with 21 additions and 17 deletions

View File

@@ -0,0 +1,6 @@
export interface RawError {
code: number;
status: string;
error_id: string;
data: null;
}

View File

@@ -1,28 +1,26 @@
import type { RawError } from '@/lib/types';
import { createFileRoute } from '@tanstack/react-router'; import { createFileRoute } from '@tanstack/react-router';
import { Suspense } from 'react'; import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { ProfileContainer } from '@/components/profile/profile.container'; import { ProfileContainer } from '@/components/profile/profile.container';
import { ProfileError } from '@/components/profile/profile.error'; import { ProfileError } from '@/components/profile/profile.error';
import { ProfileSkeleton } from '@/components/profile/profile.skeleton'; import { ProfileSkeleton } from '@/components/profile/profile.skeleton';
export const Route = createFileRoute('/_workbenchLayout/profile/$userId')({ export const Route = createFileRoute('/_workbenchLayout/profile/$userId')({
component: RouteComponent, component: RouteComponent,
errorComponent: ({ error }) => {
if ((error as unknown as RawError).code === 403)
return <ProfileError reason="用户个人资料未公开" />;
else return <ProfileError reason="获取用户个人资料失败" />;
},
}); });
function RouteComponent() { function RouteComponent() {
const { userId } = Route.useParams(); const { userId } = Route.useParams();
return ( return (
<div className="flex h-full flex-col gap-6 px-4 py-6"> <div className="flex h-full flex-col gap-6 px-4 py-6">
<ErrorBoundary fallbackRender={(error) => {
if ((error.error as { code: number }).code === 403)
return <ProfileError reason="用户个人资料未公开" />;
else return <ProfileError reason="获取用户个人资料失败" />;
}}
>
<Suspense fallback={<ProfileSkeleton />}> <Suspense fallback={<ProfileSkeleton />}>
<ProfileContainer userId={userId} /> <ProfileContainer userId={userId} />
</Suspense> </Suspense>
</ErrorBoundary>
</div> </div>
); );
} }

View File

@@ -1,21 +1,21 @@
import { createFileRoute, Navigate } from '@tanstack/react-router'; import { createFileRoute, Navigate } from '@tanstack/react-router';
import { Suspense } from 'react'; import { Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { ProfileError } from '@/components/profile/profile.error'; import { ProfileError } from '@/components/profile/profile.error';
import { ProfileSkeleton } from '@/components/profile/profile.skeleton'; import { ProfileSkeleton } from '@/components/profile/profile.skeleton';
import { useUserInfo } from '@/hooks/data/useUserInfo'; import { useUserInfo } from '@/hooks/data/useUserInfo';
export const Route = createFileRoute('/_workbenchLayout/profile/')({ export const Route = createFileRoute('/_workbenchLayout/profile/')({
component: RouteComponent, component: RouteComponent,
errorComponent: () => {
return <ProfileError reason="获取用户个人资料失败" />;
},
}); });
function RouteComponent() { function RouteComponent() {
const { data } = useUserInfo(); const { data } = useUserInfo();
return ( return (
<ErrorBoundary fallback={<ProfileError reason="获取用户个人资料失败" />}>
<Suspense fallback={<ProfileSkeleton />}> <Suspense fallback={<ProfileSkeleton />}>
<Navigate to="/profile/$userId" params={{ userId: data.data!.user_id! }} /> <Navigate to="/profile/$userId" params={{ userId: data.data!.user_id! }} />
</Suspense> </Suspense>
</ErrorBoundary>
); );
} }