一、技术栈选型与项目架构
核心技术栈
- React18(Hooks API)
- Vite
- TypeScript
- Redux Toolkit(RTK)
- React Router 6
- Ant Design
- Axios 封装
- ESLint + Prettier + Husky
- Less / CSS Modules
推荐目录结构
src
├── api # 接口封装
├── assets # 静态资源
├── components # 通用业务组件
├── config # 环境与常量
├── hooks # 自定义Hooks
├── layouts # 布局组件
├── pages # 业务页面
├── router # 路由配置
├── store # Redux Toolkit仓库
├── types # TS类型声明
├── utils # 工具函数
├── App.tsx
└── main.tsx
二、Axios 全局请求封装
src/utils/request.ts
import axios from 'axios'
import { message } from 'antd'
// 创建axios实例
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
})
// 请求拦截器
request.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => Promise.reject(error)
)
// 响应拦截器
request.interceptors.response.use(
(response) => response.data,
(error) => {
message.error(error.response?.data?.message || '请求失败')
return Promise.reject(error)
}
)
export default request
三、Redux Toolkit 状态管理
src/store/index.ts
import { configureStore, createSlice } from '@reduxjs/toolkit'
// 用户模块
const userSlice = createSlice({
name: 'user',
initialState: {
token: localStorage.getItem('token') || '',
userInfo: null,
},
reducers: {
setToken: (state, action) => {
state.token = action.payload
localStorage.setItem('token', action.payload)
},
setUserInfo: (state, action) => {
state.userInfo = action.payload
},
},
})
export const { setToken, setUserInfo } = userSlice.actions
// 配置Store
export const store = configureStore({
reducer: {
user: userSlice.reducer,
},
})
四、React Router 6 权限路由
src/router/index.tsx
import { createBrowserRouter, RouterProvider, Navigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
// 页面组件
import Login from '@/pages/Login'
import Home from '@/pages/Home'
import User from '@/pages/User'
import MainLayout from '@/layouts/MainLayout'
// 路由守卫组件
const PrivateRoute = ({ children }: { children: React.ReactNode }) => {
const { token } = useSelector((state) => state.user)
return token ? children : <Navigate to="/login" />
}
// 定义路由
const router = createBrowserRouter([
{
path: '/',
element: (
<PrivateRoute>
<MainLayout />
</PrivateRoute>
),
children: [
{ index: true, element: <Home /> },
{ path: 'user', element: <User /> },
],
},
{ path: '/login', element: <Login /> },
])
export default function Routes() {
return <RouterProvider router={router} />
}
五、React18 性能优化要点
- 组件 memo 优化
const Child = React.memo(() => {
// ...
})
- 使用 useMemo 与 useCallback
const computedValue = useMemo(() => { /* 计算逻辑 */ }, [deps])
const handleClick = useCallback(() => { /* 逻辑 */ }, [deps])
- React.lazy 与 Suspense 路由懒加载
const Home = React.lazy(() => import('@/pages/Home'))
<Suspense fallback={<div>Loading...</div>}>
<Home />
</Suspense>
六、典型业务场景实现
1. 分页搜索列表
import { Table, Input, Button, Space } from 'antd'
import { useRequest } from 'ahooks'
const UserList = () => {
const [searchParams, setSearchParams] = useState({ name: '', current: 1, pageSize: 10 })
const { data, loading } = useRequest(
() => request.get('/user/list', { params: searchParams }),
{ refreshDeps: [searchParams] }
)
const columns = [
{ title: '姓名', dataIndex: 'name', key: 'name' },
// 更多列...
]
return (
<div>
<Space style={{ marginBottom: 16 }}>
<Input
placeholder="用户名"
value={searchParams.name}
onChange={(e) => setSearchParams({ ...searchParams, name: e.target.value })}
/>
<Button onClick={() => setSearchParams({ ...searchParams, current: 1 })}>查询</Button>
</Space>
<Table
columns={columns}
dataSource={data?.list || []}
loading={loading}
pagination={{ total: data?.total || 0, current: searchParams.current, pageSize: searchParams.pageSize }}
onChange={(page) => setSearchParams({ ...searchParams, current: page.current, pageSize: page.pageSize })}
/>
</div>
)
}
七、面试高频考点
- React18 新特性(Concurrent Mode、自动批处理)
- React Hooks 规则与闭包陷阱
- Redux Toolkit 与传统 Redux 对比
- React Router 6 核心变更(布局路由、loader、action)
- 性能优化策略(memo、useMemo、useCallback)
- 状态管理方案对比(Redux、Zustand、Jotai)
——个人观点 · 仅供参考——