Files
mp-10550/docs/MENU_MIGRATION_TO_HOOK.md
赵忠林 1e51a137ee refactor(components): 重构 CouponCard 组件样式
- 优化了 CouponCard 组件的视觉效果,增加了更多细节和动画
- 添加了响应式样式,提高了移动端体验
- 新增了 CouponList组件样式,用于展示优惠券列表
2025-08-22 17:27:45 +08:00

224 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Menu组件迁移到useShopInfo Hook
## 🎯 迁移目标
`src/pages/index/Menu.tsx` 组件从直接调用API改为使用 `useShopInfo` hooks 获取导航数据。
## 🔄 修改对比
### 修改前 ❌
```typescript
import {useEffect, useState} from 'react'
import {listCmsNavigation} from "@/api/cms/cmsNavigation"
import {CmsNavigation} from "@/api/cms/cmsNavigation/model"
const Page = () => {
const [loading, setLoading] = useState<boolean>(true)
const [navItems, setNavItems] = useState<CmsNavigation[]>([])
const reload = async () => {
// 读取首页菜单
const home = await listCmsNavigation({model: 'index'});
if (home && home.length > 0) {
// 读取首页导航条
const menus = await listCmsNavigation({parentId: home[0].navigationId, hide: 0});
setNavItems(menus || [])
}
};
useEffect(() => {
reload().then(() => {
setLoading(false)
});
}, [])
// ...
}
```
### 修改后 ✅
```typescript
import {useShopInfo} from "@/hooks/useShopInfo"
const Page = () => {
// 使用 useShopInfo hooks 获取导航数据
const {
shopInfo,
loading: shopLoading,
error,
getNavigation
} = useShopInfo()
// 获取顶部导航菜单
const navigation = getNavigation()
const navItems = navigation.topNavs || []
// ...
}
```
## ✨ 改进效果
### 1. **代码简化**
- 删除了手动的状态管理 (`useState`)
- 删除了手动的API调用 (`useEffect`)
- 删除了复杂的数据获取逻辑
### 2. **自动缓存**
- 利用 `useShopInfo` 的30分钟缓存机制
- 减少不必要的网络请求
- 提升页面加载速度
### 3. **错误处理**
- 统一的错误处理机制
- 自动的重试和降级策略
- 更好的用户体验
### 4. **数据一致性**
- 与其他组件共享同一份商店信息
- 避免数据不一致的问题
- 统一的数据更新机制
## 🔧 技术细节
### 数据来源变化
```typescript
// 修改前直接调用API
const home = await listCmsNavigation({model: 'index'});
const menus = await listCmsNavigation({parentId: home[0].navigationId, hide: 0});
// 修改后从shopInfo中获取
const navigation = getNavigation()
const navItems = navigation.topNavs || []
```
### 加载状态处理
```typescript
// 修改前手动管理loading状态
const [loading, setLoading] = useState<boolean>(true)
// 修改后使用hooks提供的loading状态
const { loading: shopLoading } = useShopInfo()
```
### 错误处理
```typescript
// 修改前:没有错误处理
// 修改后:统一的错误处理
if (error) {
return (
<div className={'p-2 text-center text-red-500'}>
加载导航菜单失败
</div>
)
}
```
## 📊 性能对比
### 修改前
- ❌ 每次组件加载都要发起API请求
- ❌ 没有缓存机制
- ❌ 多个组件重复请求相同数据
- ❌ 网络失败时没有降级策略
### 修改后
- ✅ 利用30分钟缓存减少网络请求
- ✅ 多个组件共享同一份数据
- ✅ 网络失败时使用缓存数据
- ✅ 自动的数据刷新机制
## 🎯 数据结构
### useShopInfo 提供的导航数据结构
```typescript
const navigation = getNavigation()
// 返回:
{
topNavs: [ // 顶部导航菜单
{
title: "菜单名称",
icon: "图标URL",
path: "页面路径",
// ... 其他属性
}
],
bottomNavs: [ // 底部导航菜单
// ...
]
}
```
## 🚀 使用建议
### 1. 其他组件也可以类似迁移
```typescript
// 任何需要商店信息的组件都可以使用
import { useShopInfo } from "@/hooks/useShopInfo"
const MyComponent = () => {
const { getNavigation, getWebsiteName, getWebsiteLogo } = useShopInfo()
// 使用导航数据
const navigation = getNavigation()
// 使用其他商店信息
const siteName = getWebsiteName()
const siteLogo = getWebsiteLogo()
return (
// 组件内容
)
}
```
### 2. 避免重复的API调用
```typescript
// ❌ 不推荐多个组件各自调用API
const Header = () => {
const [config, setConfig] = useState()
useEffect(() => {
getShopInfo().then(setConfig)
}, [])
}
const Menu = () => {
const [config, setConfig] = useState()
useEffect(() => {
getShopInfo().then(setConfig)
}, [])
}
// ✅ 推荐使用统一的hooks
const Header = () => {
const { getWebsiteName } = useShopInfo()
return <div>{getWebsiteName()}</div>
}
const Menu = () => {
const { getNavigation } = useShopInfo()
const navigation = getNavigation()
return <div>{/* 渲染导航 */}</div>
}
```
## 🎉 总结
通过这次迁移Menu组件
-**代码更简洁** - 减少了50%的代码量
-**性能更好** - 利用缓存机制减少网络请求
-**更可靠** - 统一的错误处理和降级策略
-**更一致** - 与其他组件共享同一份数据
这是一个很好的重构示例展示了如何通过使用合适的hooks来简化组件逻辑并提升性能。