React18+TypeScript状态管理最佳实践

发布于:2025-07-09 ⋅ 阅读:(22) ⋅ 点赞:(0)

目录

一、核心概念与流程

1. ​​createContext 的作用​​

2. ​​useContext 的作用​​

二、在 Ant Design Pro v6 中的实现步骤

1. ​​封装 Provider 组件​​

2. ​​集成到全局布局​​

3. ​​组件中消费状态​​

三、性能优化技巧

1. ​​避免无效渲染​​

2. ​​自定义 Hook 封装​​

四、常见场景与避坑指南

1. ​​典型应用场景​​

2. ​​关键注意事项​​

五、完整案例:主题切换实现

总结


在 Ant Design Pro v6(基于 Umi 4 + React 18+)与 TypeScript 中,createContextuseContext 是管理跨组件状态的核心工具。以下是结合最佳实践的系统指南:


一、核心概念与流程

1. ​createContext 的作用​

创建上下文对象,包含 Provider(提供数据)和 Consumer(消费数据,已被 useContext 替代)。

  • ​TypeScript 强类型定义​​:避免运行时错误,明确上下文结构:
    // src/contexts/UserContext.ts
    import { createContext } from 'react';
    
    interface UserContextType {
      name: string;
      role: 'admin' | 'user';
      setUser: (user: Partial<UserContextType>) => void;
    }
    
    export const UserContext = createContext<UserContextType | null>(null);
2. ​useContext 的作用​

在函数组件中消费上下文值,避免逐层传递 props:

const userContext = useContext(UserContext);
if (!userContext) throw new Error('未在 Provider 内使用!');
return userContext;

二、在 Ant Design Pro v6 中的实现步骤

1. ​​封装 Provider 组件​

/src/contexts 目录下创建 Provider,结合 useStateuseReducer 管理状态:

// src/contexts/UserProvider.tsx
import { ReactNode, useState } from 'react';
import { UserContext } from './UserContext';

export default ({ children }: { children: ReactNode }) => {
  const [user, setUser] = useState({ name: '', role: 'user' });
  
  const contextValue = {
    ...user,
    setUser: (updates: Partial<UserContextType>) => 
      setUser(prev => ({ ...prev, ...updates }))
  };

  return (
    <UserContext.Provider value={contextValue}>
      {children}
    </UserContext.Provider>
  );
};
2. ​​集成到全局布局​

src/app.tsx 中包裹全局组件,确保所有页面可访问上下文:

// src/app.tsx
import UserProvider from '@/contexts/UserProvider';

export function rootContainer(container: ReactNode) {
  return <UserProvider>{container}</UserProvider>;
}
3. ​​组件中消费状态​

直接通过 useContext 获取数据或更新函数:

// src/pages/Profile/index.tsx
import { UserContext } from '@/contexts/UserContext';

export default () => {
  const { name, setUser } = useContext(UserContext)!;
  
  return (
    <Button onClick={() => setUser({ name: 'Admin' })}>
      更新用户:{name}
    </Button>
  );
};

三、性能优化技巧

1. ​​避免无效渲染​
  • ​拆分上下文​​:将频繁变更的状态(如用户输入)与静态数据(如配置)分离。
    const UserConfigContext = createContext<ConfigType>(null!);
    const UserStateContext = createContext<StateType>(null!);
  • ​缓存 value 对象​​:使用 useMemo 减少重渲染:
    const contextValue = useMemo(() => ({ user, setUser }), [user]);
2. ​​自定义 Hook 封装​

提供类型安全提示,简化调用:

// src/hooks/useUser.ts
export default () => {
  const context = useContext(UserContext);
  if (!context) throw new Error('UserContext 未初始化');
  return context;
};

四、常见场景与避坑指南

1. ​​典型应用场景​
  • 用户身份认证状态
  • 主题切换(深色/浅色模式)
  • 多语言国际化(结合 umi-plugin-locale
  • 全局弹窗/通知控制
2. ​​关键注意事项​
  • ​默认值问题​​:未包裹 Provider 时返回 createContext 的默认值,需做好错误处理。
  • ​嵌套顺序​​:内层 Provider 会覆盖外层同名 Context
  • ​异步更新​​:在 useEffect 中更新上下文时,需考虑依赖项避免死循环。

五、完整案例:主题切换实现

// 1. 定义主题上下文
const ThemeContext = createContext<{
  theme: 'light' | 'dark';
  toggleTheme: () => void;
} | null>(null);

// 2. 创建 Provider
export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');
  const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
  const value = useMemo(() => ({ theme, toggleTheme }), [theme]);

  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
};

// 3. 在组件中使用
const ThemeButton = () => {
  const { theme, toggleTheme } = useContext(ThemeContext)!;
  return (
    <Button onClick={toggleTheme}>
      当前主题:{theme}
    </Button>
  );
};

总结

在 Ant Design Pro v6 + TypeScript 技术栈中:

  1. ​强类型定义​​是基础,避免空值错误;
  2. ​Provider 全局挂载​​确保跨组件共享状态;
  3. ​性能优化​​优先考虑上下文拆分与 useMemo
  4. ​自定义 Hook​​ 提升代码复用率与可维护性。

通过上下文管理轻量级全局状态,可减少对 Redux 的依赖,保持项目简洁性。


网站公告

今日签到

点亮在社区的每一天
去签到