Refine v5 + shadcn/ui:打造可复用的 ErrorComponent 404 错误页
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
在 Refine v5 的 shadcn/ui 技术栈中,ErrorComponent是 refine-ui 组件注册表(registry)提供的一个 404 错误页组件:当用户访问了不存在的链接,或导航到了尚未实现的资源页面时,它会展示一个带有清晰文案、404 视觉图形和"返回首页"按钮的错误页,帮助用户优雅地从错误中恢复,而不是面对浏览器默认的 404 提示。读完本文,你将掌握通过 shadcn CLI 安装该组件、将其接入路由作为 catch-all 404 页面的完整流程,并能基于源码理解其国际化文案、资源缺失提示(Tooltip)与useGo导航跳转的实现机制,以及它与@refinedev/core内置ErrorComponent的差异。
组件概览
根据文档 shadcn/ui ErrorComponent,该组件的定位是:为管理后台提供一个"打磨过的"错误页面,包含明确的错误消息、视觉图形和导航选项,且会自动适配你的主题设置,与仪表盘其余部分保持视觉一致。
在仓库中,该组件的源码实现位于 error-component.tsx,其 shadcn registry 元数据(安装清单)位于 error-component.json。从 registry 清单可以确认它的关键属性:
| 属性 | 值 | 说明 |
|---|---|---|
name | error-component | registry 中的组件名 |
type | registry:component | 作为 shadcn 组件被安装 |
dependencies | @refinedev/core、lucide-react | 安装时自动加入 npm 依赖 |
registryDependencies | button、tooltip | 安装时一并拉取的 shadcn 基础组件 |
files[0].target | src/components/refine-ui/layout/error-component.tsx | 落地到项目中的目标路径 |
categories | error、layout、404、pages | 分类标签 |
也就是说,它依赖@refinedev/core提供的useGo、useResourceParams、useTranslate三个 Hook,依赖lucide-react提供ChevronLeft、InfoIcon图标,并复用 shadcn 的Button与Tooltip组件。
安装
文档给出的安装命令是:
npx shadcn@latest add https://ui.refine.dev/r/error-component.json这条命令会:
- 从 refine 的 shadcn registry 拉取 error-component.json 清单;
- 自动安装
@refinedev/core与lucide-react两个包依赖,以及button、tooltip两个 registry 基础组件; - 将组件文件写入项目的
src/components/refine-ui/layout/error-component.tsx(对应清单中的target字段)。
安装完成后,你得到的就是一个"带返回首页导航的完整 404 错误页",无需再手写任何布局代码。
使用
将组件作为 404 页面直接使用:
import { ErrorComponent } from "@/components/refine-ui/layout/error-component"; export default function NotFoundPage() { return <ErrorComponent />; }组件会自动提供友好的错误消息和返回应用首页的按钮,并适配主题设置,保持与仪表盘其他部分的视觉一致性。
与路由集成:作为 catch-all 404 路由
在大多数 React Router 项目中,可以把该组件用作通配路由(catch-all route):
// In your routing configuration import { ErrorComponent } from "@/components/refine-ui/layout/error-component"; function App() { return ( <Routes> {/* Your other routes */} <Route path="*" element={<ErrorComponent />} /> </Routes> ); }这个"catch-all 写法"并不是孤立的示例。从源码结构看,Refine CLI 在检测到项目已有 React Router 配置时,就会自动生成完全相同的路由形态:react-router.ts 会向App中注入@refinedev/core的ErrorComponent并添加<Route path="*" element={<ErrorComponent />} />,其测试夹具 with-existing-react-router-setup.ts 中展示的正是这一结构。对于 shadcn 技术栈,只是把导入源换成了 refine-ui registry 中样式更精致的这个实现。
另外需要注意 v5 的导入位置变化:v5 的 codemod 测试 rename-themed-v2-imports.test.ts 显示,旧版本中ErrorComponent从@refinedev/antd、@refinedev/mui等 UI 包导出,v5 迁移时会被自动改写导入路径。如果你在老项目中看到import { ErrorComponent } from "@refinedev/antd",可以运行 codemod 或手动改为从 core / refine-ui 导入。
源码深潜:shadcn 版 ErrorComponent 如何工作
下面结合 error-component.tsx 的完整实现逐段拆解。
三个核心 Hook:useTranslate、useGo、useResourceParams
const [errorMessage, setErrorMessage] = useState<string>(); const translate = useTranslate(); const go = useGo(); const { resource, action } = useResourceParams();useResourceParams():从当前路由中解析出resource(资源,如posts)与action(动作,如create、list)。这是 Refine 路由约定/:resource/:action的直接产物;useGo():Refine 的跨路由导航 Hook,底层委托给路由 provider(React Router、Next.js Router 等)的go实现;useTranslate():国际化 Hook,所有可见文案都通过它渲染,未配置 i18n 时使用传入的英文默认值。
资源缺失提示:Tooltip 的显示逻辑
组件通过useEffect监听路由参数,决定是否需要显示一条"开发者提示"(源码 L28-L41):
useEffect(() => { if (resource && action) { setErrorMessage( translate( "pages.error.info", { action: action, resource: resource?.name, }, `You may have forgotten to add the "${action}" component to "${resource?.name}" resource.`, ), ); } }, [resource, action, translate]);这里体现了一个很有价值的错误页设计思路:
- 访问的是任意不存在的路径(如
/foo/bar):resource与action都为空,只显示通用 404 文案; - 访问的是符合 Refine 约定但组件缺失的页面(如路由解析出了
resource: "posts"、action: "create",却没有注册对应的 Create 页面):错误页会在描述文案旁显示一个InfoIcon图标,悬停 Tooltip 提示"You may have forgotten to add the 'create' component to 'posts' resource.",直接告诉开发者缺的是哪个资源的哪个页面,大幅缩短排障时间。
对应源码 L98-L117 的渲染结构为:TooltipProvider > Tooltip > TooltipTrigger(asChild, InfoIcon) > TooltipContent,且只有errorMessage存在时才渲染,图标上还带有data-testid="error-component-tooltip"便于 E2E 测试定位。
视觉与布局
组件使用 Tailwind 类名(通过cn工具函数合并,见源码 L43-L52)构建:
- 外层容器
flex items-center justify-center bg-background my-auto,让 404 页面在整个视口中垂直水平居中,并使用主题 tokenbg-background保证深浅色主题下都正确; - 中间的"404"字样是一个内联 SVG(L55-L81),使用
#D4D4D8 -> #E4E4E7的线性渐变填充,宽度固定w-48、高度自适应; - 标题
text-2xl font-semibold text-foreground,描述文案text-muted-foreground,同样全部使用语义化颜色 token,天然跟随主题切换。
返回首页按钮
按钮实现(源码 L121-L129):
<Button onClick={() => { go({ to: "/" }); }} className={cn("flex", "items-center", "gap-2", "mx-auto")} > <ChevronLeft className={cn("h-4", "w-4")} /> {translate("pages.error.backHome", "Back to hompeage")} </Button>点击后调用go({ to: "/" })导航回应用根路径。由于useGo抽象了具体路由实现,同一段代码在 React Router、Next.js、Remix 等任何 Refine 支持的路由器下都能工作。
国际化文案键
shadcn 版组件使用以下翻译键(第二个参数为无 i18n 配置时的英文回退值):
| 翻译键 | 默认文案 | 出现位置 |
|---|---|---|
pages.error.title | Page not found. | 页面标题(h1) |
pages.error.description | The page you're looking for does not exist. | 描述段落 |
pages.error.info | You may have forgotten to add the "{action}" component to "{resource}" resource. | 资源缺失时的 Tooltip |
pages.error.backHome | Back to hompeage | 返回按钮 |
如果你的应用配置了i18nProvider,只需在语言包中提供这些键的翻译,整个错误页即可完全本地化。
与 @refinedev/core 内置 ErrorComponent 的关系
Refine core 一直内置一个无样式的ErrorComponent(packages/core/src/components/pages/error/index.tsx),逻辑与 shadcn 版几乎一致:同样使用useTranslate/useGo/useResourceParams,同样在存在resource与action时生成资源缺失提示文案,按钮同样执行go({ to: "/" })。两者的差异主要在呈现层:
- core 版:仅输出原生
<h1>、<p>、<button>,翻译键为pages.error.404/pages.error.info/pages.error.backHome,适合 headless 场景或自定义 UI 的基础; - shadcn 版:使用 shadcn
Button/Tooltip、内联 404 SVG 与 Tailwind 主题 token,标题与描述拆分为pages.error.title/pages.error.description两个键,视觉更精致且自带交互提示。
core 版的行为有完整测试佐证(index.spec.tsx):当 mock 路由 provider 给出action: "create"、resource: { name: "posts" }时,页面会渲染"You may have forgotten to add the 'create' component to 'posts' resource.";点击 Back Home 后go恰被调用一次且参数为{ to: "/" }。这验证了两版组件共享同一套错误语义。
小结与最佳实践
- 安装:
npx shadcn@latest add https://ui.refine.dev/r/error-component.json,组件落地到src/components/refine-ui/layout/error-component.tsx,自动补齐@refinedev/core、lucide-react与 button/tooltip 依赖; - 路由接入:在
<Routes>末尾声明<Route path="*" element={<ErrorComponent />} />,即可覆盖所有未匹配路径; - 利用资源提示:当 URL 符合
/:resource/:action约定但页面缺失时,错误页 Tooltip 会直接指出缺失的资源与动作,这是排查"路由配了但忘写页面"类问题最快的入口; - 跟随主题与 i18n:组件只使用语义化颜色 token 与翻译键,接入你的 shadcn 主题和 i18nProvider 后无需任何额外适配;
- 区分使用场景:headless 项目可用
@refinedev/core内置版自行定制;shadcn 技术栈则优先使用 refine-ui registry 的这版实现,保持与 refine-ui 其他视图(list/create/edit 等)一致的视觉语言。
相关参考路径:组件源码 packages/refine-ui/registry/new-york/refine-ui/layout/error-component.tsx、registry 清单 packages/refine-ui/public/r/error-component.json、core 内置实现 packages/core/src/components/pages/error/index.tsx 及其测试 packages/core/src/components/pages/error/index.spec.tsx。
【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考