您的位置:首页 > 健康 > 美食 > 网站建设设备_浙江建筑协会网站_宁波seo免费优化软件_2024年新闻摘抄十条

网站建设设备_浙江建筑协会网站_宁波seo免费优化软件_2024年新闻摘抄十条

2024/12/21 22:46:47 来源:https://blog.csdn.net/ChengFengTech/article/details/144418596  浏览:    关键词:网站建设设备_浙江建筑协会网站_宁波seo免费优化软件_2024年新闻摘抄十条
网站建设设备_浙江建筑协会网站_宁波seo免费优化软件_2024年新闻摘抄十条

"老师,我们的后台管理系统状态管理好混乱啊!"上周二的代码评审会上,小王一脸苦恼地说道。我打开代码仓库看了看,确实问题不小 - Redux store 里堆满了各种数据,有本地状态,有服务器数据,还有一些缓存,导致代码难以维护,性能也受到影响。

说实话,这个问题在中后台项目中很常见。随着项目的发展,状态管理往往会变得越来越复杂。今天就来分享一下我们是如何通过重构解决这个问题的。

问题的症状

首先,让我们看看重构前的代码是什么样子:

// 原来的 Redux store
interface AppState {// 本地 UI 状态ui: {theme: stringsidebar: booleanmodal: {visible: booleantype: string}}// 服务器数据users: {list: User[]loading: booleanerror: Error | nulllastUpdated: number}products: {list: Product[]loading: booleanerror: Error | nulllastUpdated: number}// 表单状态forms: {userForm: {values: anyerrors: anytouched: boolean[]}productForm: {values: anyerrors: anytouched: boolean[]}}
}// 获取用户数据的 action
const fetchUsers = () => async dispatch => {dispatch({ type: 'FETCH_USERS_START' })try {const response = await api.get('/users')dispatch({type: 'FETCH_USERS_SUCCESS',payload: response.data,lastUpdated: Date.now()})} catch (error) {dispatch({ type: 'FETCH_USERS_ERROR', error })}
}// 组件中的使用
function UserList() {const dispatch = useDispatch()const { list: users, loading, error } = useSelector(state => state.users)useEffect(() => {dispatch(fetchUsers())}, [dispatch])if (loading) return <Loading />if (error) return <Error message={error.message} />return (<div>{users.map(user => (<UserCard key={user.id} user={user} />))}</div>)
}

这种方式存在几个明显的问题:

  1. 服务器状态和客户端状态混在一起
  2. 大量重复的样板代码
  3. 缓存和数据同步困难
  4. 性能优化不好做

重构方案

经过团队讨论,我们决定采用"分而治之"的策略:

  1. 使用 React Query 管理 服务器状态
  2. 使用 Zustand 管理本地 UI 状态
  3. 使用 React Hook Form 管理表单状态
// 使用 React Query 管理服务器状态
function useUsers() {return useQuery({queryKey: ['users'],queryFn: () => api.get('/users').then(res => res.data),staleTime: 5 * 60 * 1000, // 5分钟内认为数据是新鲜的cacheTime: 30 * 60 * 1000 // 缓存30分钟})
}// 使用 Zustand 管理 UI 状态
interface UIStore {theme: stringsidebar: booleansetTheme: (theme: string) => voidtoggleSidebar: () => void
}const useUIStore = create<UIStore>(set => ({theme: 'light',sidebar: true,setTheme: theme => set({ theme }),toggleSidebar: () => set(state => ({ sidebar: !state.sidebar }))
}))// 使用 React Hook Form 管理表单
function UserForm() {const {register,handleSubmit,formState: { errors }} = useForm<UserFormData>()const queryClient = useQueryClient()const mutation = useMutation({mutationFn: (data: UserFormData) => api.post('/users', data),onSuccess: () => {// 成功后使缓存失效queryClient.invalidateQueries({ queryKey: ['users'] })}})const onSubmit = handleSubmit(data => {mutation.mutate(data)})return (<form onSubmit={onSubmit}><input {...register('name', { required: true })} />{errors.name && <span>名字是必填的</span>}<button type='submit'>提交</button></form>)
}

重构过程

为了平滑过渡,我们采用了渐进式重构策略:

  1. 首先创建一个自定义 Hook 封装数据获取逻辑:
// hooks/useResource.ts
function useResource<T>(resource: string) {const query = useQuery({queryKey: [resource],queryFn: () => api.get(`/${resource}`).then(res => res.data),// 配置缓存策略staleTime: 5 * 60 * 1000,cacheTime: 30 * 60 * 1000,// 乐观更新配置optimisticResults: true,// 重试策略retry: 3,retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000)})const mutation = useMutation({mutationFn: (data: Partial<T>) => api.post(`/${resource}`, data),onSuccess: () => {// 更新缓存query.invalidate()}})return {data: query.data,isLoading: query.isLoading,error: query.error,create: mutation.mutate,isCreating: mutation.isLoading}
}// 使用示例
function UserList() {const { data: users, isLoading, error } = useResource<User>('users')if (isLoading) return <Loading />if (error) return <Error message={error.message} />return (<div>{users.map(user => (<UserCard key={user.id} user={user} />))}</div>)
}
  1. 然后逐步迁移状态管理:
// 新的状态管理结构
interface AppState {// Zustand 管理 UI 状态ui: UIStore// React Query 管理服务器状态// - 用户数据// - 产品数据// - 订单数据// React Hook Form 管理表单状态// - 用户表单// - 产品表单
}// 性能优化
function UserList() {const { data: users, isLoading } = useResource<User>('users')// 使用 React Query 的内置缓存const { data: roles } = useQuery({queryKey: ['roles'],queryFn: () => api.get('/roles').then(res => res.data),// 只有当有用户数据时才获取角色enabled: !!users})// 使用 memo 优化渲染const userCards = useMemo(() => users?.map(user => <UserCard key={user.id} user={user} role={roles?.find(role => role.id === user.roleId)} />), [users, roles])if (isLoading) return <Loading />return <div>{userCards}</div>
}

效果验证

重构后,我们观察到了明显的改善:

  1. 代码更清晰,职责划分明确
  2. 缓存管理更智能,性能提升明显
  3. 开发效率提高,不用写那么多样板 代 码
  4. 数据同步问题大大减少

最让我印象深刻的是小王的反馈:"现在代码写起来舒服多了,不用担心状态同步的问题!"

经验总结

这次重构让我们学到了很多:

  1. 不同类型的状态要用不同的工具管理
  2. 缓存策略要根据业务场景来设计
  3. 渐进式重构比大规模重写更可控
  4. 好的抽象能大大提高开发效率

就像整理房间一样,不同类型的物品要放在不同的地方。把衣服、书籍、电子产品分类存放,不仅容易找,也更好维护。状态管理也是一样,合适的工具管理合适的状态,才能让代码更清晰、更好维护。

写在最后

状态管理没有银弹,关键是要根据实际需求选择合适的方案。就像选择家具一样,不是越贵越好,而是要适合自己的需求。

有什么问题欢迎在评论区讨论,让我们一起探讨状态管理的最佳实践!

如果觉得有帮助,别忘了点赞关注,我会继续分享更多实战经验~

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com