前端開發指南
目的
現代 React 開發的綜合指南,強調基於 Suspense 的資料擷取、惰性加載、適當的檔案組織以及效能優化。
何時使用此技能
- 建立新元件或頁面
- 構建新功能
- 使用 TanStack Query 擷取資料
- 使用 TanStack Router 設定路由
- 使用 MUI v7 設計元件樣式
- 效能優化
- 組織前端程式碼
- TypeScript 最佳實踐
快速入門
新元件檢查清單
正在建立元件?請遵循此檢查清單:
- 使用帶有 TypeScript 的
React.FC<Props>模式 - 如果是重量級元件,請惰性加載:
React.lazy(() => import()) - 包裹在
<SuspenseLoader>中以處理加載狀態 - 使用
useSuspenseQuery進行資料擷取 - 匯入別名:
@/、~types、~components、~features - 樣式:少於 100 行則內聯,超過 100 行則使用單獨檔案
- 對傳遞給子元件的事件處理器使用
useCallback - 在底部使用預設匯出
- 不要使用帶有加載旋轉器的早期返回
- 使用
useMuiSnackbar進行使用者通知
新功能檢查清單
正在建立功能?請設定此結構:
- 建立
features/{feature-name}/目錄 - 建立子目錄:
api/、components/、hooks/、helpers/、types/ - 建立 API 服務檔案:
api/{feature}Api.ts - 在
types/中設定 TypeScript 型別 - 在
routes/{feature-name}/index.tsx中建立路由 - 惰性加載功能元件
- 使用 Suspense 邊界
- 從功能
index.ts匯出公開 API
匯入別名快速參考
| 別名 | 解析到 | 範例 |
|---|---|---|
@/ | src/ | import { apiClient } from '@/lib/apiClient' |
~types | src/types | import type { User } from '~types/user' |
~components | src/components | import { SuspenseLoader } from '~components/SuspenseLoader' |
~features | src/features | import { authApi } from '~features/auth' |
定義於:vite.config.ts 第 180-185 行
常見匯入小抄
// React 與惰性加載
import React, { useState, useCallback, useMemo } from 'react';
const Heavy = React.lazy(() => import('./Heavy'));
// MUI 元件
import { Box, Paper, Typography, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
// TanStack Query(Suspense)
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
// TanStack Router
import { createFileRoute } from '@tanstack/react-router';
// 專案元件
import { SuspenseLoader } from '~components/SuspenseLoader';
// Hooks
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
// 型別
import type { Post } from '~types/post';
主題指南
🎨 元件模式
現代 React 元件使用:
React.FC<Props>以獲得型別安全React.lazy()進行程式碼分割SuspenseLoader處理加載狀態- 具名常數 + 預設匯出模式
關鍵概念:
- 惰性加載重量級元件(DataGrid、圖表、編輯器)
- 始終將惰性元件包裹在 Suspense 中
- 使用 SuspenseLoader 元件(帶有淡入動畫)
- 元件結構:Props → Hooks → Handlers → Render → Export
📖 完整指南:resources/component-patterns.md
📊 資料擷取
主要模式:useSuspenseQuery
- 與 Suspense 邊界一起使用
- 快取優先策略(在 API 呼叫前檢查網格快取)
- 取代
isLoading檢查 - 使用泛型獲得型別安全
API 服務層:
- 建立
features/{feature}/api/{feature}Api.ts - 使用
apiClientaxios 實例 - 每個功能的集中化方法
- 路由格式:
/form/route(而非/api/form/route)
📖 完整指南:resources/data-fetching.md
📁 檔案組織
features/ 與 components/ 的區別:
features/:領域特定(文章、留言、認證)components/:真正可重用(SuspenseLoader、CustomAppBar)
功能子目錄:
features/
my-feature/
api/ # API 服務層
components/ # 功能元件
hooks/ # 自訂 Hooks
helpers/ # 工具函數
types/ # TypeScript 型別
📖 完整指南:resources/file-organization.md
🎨 樣式設計
內聯 vs 分離:
- 少於 100 行:內聯
const styles: Record<string, SxProps<Theme>> - 超過 100 行:分離的
.styles.ts檔案
主要方法:
- 對 MUI 元件使用
sxprop - 使用
SxProps<Theme>獲得型別安全 - 主題存取:
(theme) => theme.palette.primary.main
MUI v7 Grid:
<Grid size={{ xs: 12, md: 6 }}> // ✅ v7 語法
<Grid xs={12} md={6}> // ❌ 舊語法
📖 完整指南:resources/styling-guide.md
🛣️ 路由
TanStack Router - 基於資料夾:
- 目錄:
routes/my-route/index.tsx - 惰性加載元件
- 使用
createFileRoute - 在 loader 中設定麵包屑資料
範例:
import { createFileRoute } from '@tanstack/react-router';
import { lazy } from 'react';
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));
export const Route = createFileRoute('/my-route/')({
component: MyPage,
loader: () => ({ crumb: 'My Route' }),
});
📖 完整指南:resources/routing-guide.md
⏳ 加載與錯誤狀態
關鍵規則:禁止早期返回
// ❌ 永不 - 導致版面位移
if (isLoading) {
return <LoadingSpinner />;
}
// ✅ 始終 - 一致的版面
<SuspenseLoader>
<Content />
</SuspenseLoader>
原因: 防止累積版面位移(CLS),更好的使用者體驗
錯誤處理:
- 使用
useMuiSnackbar進行使用者回饋 - 永不使用
react-toastify - TanStack Query 的
onError回呼
📖 完整指南:resources/loading-and-error-states.md
⚡ 效能
優化模式:
useMemo:昂貴的計算(過濾、排序、映射)useCallback:傳遞給子元件的事件處理器React.memo:昂貴的元件- 防抖搜尋(300-500ms)
- 記憶體洩漏預防(在 useEffect 中清理)
📖 完整指南:resources/performance.md
📘 TypeScript
標準:
- 嚴格模式,不使用
any型別 - 函數明確的返回型別
- 型別匯入:
import type { User } from '~types/user' - 帶有 JSDoc 的元件 prop 介面
📖 完整指南:resources/typescript-standards.md
🔧 常見模式
涵蓋主題:
- 帶有 Zod 驗證的 React Hook Form
- DataGrid 包裹合約
- 對話框元件標準
- 用於當前使用者的
useAuthhook - 帶有快取失效的 Mutation 模式
📖 完整指南:resources/common-patterns.md
📚 完整範例
完整運作範例:
- 包含所有模式的現代元件
- 完整的功能結構
- API 服務層
- 帶有惰性加載的路由
- Suspense + useSuspenseQuery
- 帶有驗證的表單
📖 完整指南:resources/complete-examples.md
導航指南
| 需要... | 請閱讀此資源 |
|---|---|
| 建立元件 | component-patterns.md |
| 擷取資料 | data-fetching.md |
| 組織檔案/資料夾 | file-organization.md |
| 設計元件樣式 | styling-guide.md |
| 設定路由 | routing-guide.md |
| 處理加載/錯誤 | loading-and-error-states.md |
| 優化效能 | performance.md |
| TypeScript 型別 | typescript-standards.md |
| 表單/認證/DataGrid | common-patterns.md |
| 查看完整範例 | complete-examples.md |
核心原則
- 惰性加載所有重量級項目:路由、DataGrid、圖表、編輯器
- 使用 Suspense 處理加載:使用 SuspenseLoader,而非早期返回
- useSuspenseQuery:新程式碼的主要資料擷取模式
- 功能組織有序:api/、components/、hooks/、helpers/ 子目錄
- 根據大小決定樣式:少於 100 行內聯,超過 100 行分離
- 匯入別名:使用 @/、~types、~components、~features
- 禁止早期返回:防止版面位移
- useMuiSnackbar:用於所有使用者通知
快速參考:檔案結構
src/
features/
my-feature/
api/
myFeatureApi.ts # API 服務
components/
MyFeature.tsx # 主要元件
SubComponent.tsx # 相關元件
hooks/
useMyFeature.ts # 自訂 Hooks
useSuspenseMyFeature.ts # Suspense Hooks
helpers/
myFeatureHelpers.ts # 工具函數
types/
index.ts # TypeScript 型別
index.ts # 公開匯出
components/
SuspenseLoader/
SuspenseLoader.tsx # 可重複使用的加載器
CustomAppBar/
CustomAppBar.tsx # 可重複使用的應用程式欄
routes/
my-route/
index.tsx # 路由元件
create/
index.tsx # 巢狀路由
現代元件模板(快速複製)
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';
import { featureApi } from '../api/featureApi';
import type { FeatureData } from '~types/feature';
interface MyComponentProps {
id: number;
onAction?: () => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ id, onAction }) => {
const [state, setState] = useState<string>('');
const { data } = useSuspenseQuery({
queryKey: ['feature', id],
queryFn: () => featureApi.getFeature(id),
});
const handleAction = useCallback(() => {
setState('updated');
onAction?.();
}, [onAction]);
return (
<Box sx={{ p: 2 }}>
<Paper sx={{ p: 3 }}>
{/* 內容 */}
</Paper>
</Box>
);
};
export default MyComponent;
如需完整範例,請參閱 resources/complete-examples.md
相關技能
- error-tracking:使用 Sentry 進行錯誤追蹤(也適用於前端)
- backend-dev-guidelines:前端使用的後端 API 模式
技能狀態:模組化結構,具有漸進式加載,以獲得最佳上下文管理