1. 基本概念
1.1 什么是 Context
Context 提供了一种在组件树中共享数据的方式,而不必通过 props 显式地逐层传递。它主要用于共享那些对于组件树中许多组件来说是"全局"的数据。
1.2 基本用法
// 1. 创建 Context
const ThemeContext = React.createContext('light');// 2. 提供 Context
function App() {return (<ThemeContext.Provider value="dark"><Toolbar /></ThemeContext.Provider>);
}// 3. 消费 Context
function Toolbar() {return (<div><ThemedButton /></div>);
}function ThemedButton() {const theme = React.useContext(ThemeContext);return <button className={theme}>Themed Button</button>;
}
2. Context API 详解
2.1 创建 Context
// 创建 Context 并设置默认值
const UserContext = React.createContext({name: 'Guest',isAdmin: false
});// 导出 Context 供其他组件使用
export default UserContext;
2.2 Provider 组件
function App() {const [user, setUser] = useState({name: 'John',isAdmin: true});return (<UserContext.Provider value={user}><div className="app"><MainContent /><Sidebar /></div></UserContext.Provider>);
}
2.3 消费 Context
使用 useContext Hook(推荐)
function UserProfile() {const user = React.useContext(UserContext);return (<div><h2>User Profile</h2><p>Name: {user.name}</p><p>Role: {user.isAdmin ? 'Admin' : 'User'}</p></div>);
}
使用 Consumer 组件
function UserRole() {return (<UserContext.Consumer>{user => (<span>Role: {user.isAdmin ? 'Admin' : 'User'}</span>)}</UserContext.Consumer>);
}
3. 高级用法
3.1 多个 Context 组合
const ThemeContext = React.createContext('light');
const UserContext = React.createContext({ name: 'Guest' });function App() {return (<ThemeContext.Provider value="dark"><UserContext.Provider value={{ name: 'John' }}><Layout /></UserContext.Provider></ThemeContext.Provider>);
}function Layout() {const theme = React.useContext(ThemeContext);const user = React.useContext(UserContext);return (<div className={theme}><header>Welcome, {user.name}</header><main>Content</main></div>);
}
3.2 动态 Context
const ThemeContext = React.createContext({theme: 'light',toggleTheme: () => {}
});function ThemeProvider({ children }) {const [theme, setTheme] = useState('light');const toggleTheme = () => {setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');};return (<ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>);
}function ThemeToggleButton() {const { theme, toggleTheme } = React.useContext(ThemeContext);return (<button onClick={toggleTheme}>Current theme: {theme}</button>);
}
3.3 Context 与 TypeScript
// 定义 Context 类型
interface UserContextType {name: string;isAdmin: boolean;updateUser: (name: string) => void;
}const UserContext = React.createContext<UserContextType | undefined>(undefined);// 创建自定义 Hook
function useUser() {const context = React.useContext(UserContext);if (context === undefined) {throw new Error('useUser must be used within a UserProvider');}return context;
}// Provider 组件
function UserProvider({ children }: { children: React.ReactNode }) {const [name, setName] = useState('Guest');const [isAdmin] = useState(false);const updateUser = (newName: string) => {setName(newName);};return (<UserContext.Provider value={{ name, isAdmin, updateUser }}>{children}</UserContext.Provider>);
}
4. 最佳实践
4.1 创建自定义 Hook
// 创建自定义 Hook 封装 Context 逻辑
function useTheme() {const context = React.useContext(ThemeContext);if (context === undefined) {throw new Error('useTheme must be used within a ThemeProvider');}return context;
}// 使用自定义 Hook
function ThemedButton() {const { theme, toggleTheme } = useTheme();return (<button onClick={toggleTheme} className={theme}>Toggle Theme</button>);
}
4.2 分离 Context 逻辑
// contexts/theme.js
export const ThemeContext = React.createContext({theme: 'light',toggleTheme: () => {}
});export function ThemeProvider({ children }) {const [theme, setTheme] = useState('light');const value = {theme,toggleTheme: () => setTheme(t => t === 'light' ? 'dark' : 'light')};return (<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>);
}export function useTheme() {const context = React.useContext(ThemeContext);if (context === undefined) {throw new Error('useTheme must be used within a ThemeProvider');}return context;
}
4.3 性能优化
// 使用 memo 避免不必要的重渲染
const UserInfo = React.memo(function UserInfo() {const { name } = useUser();return <div>User: {name}</div>;
});// 分离状态,避免不相关的更新
function AppProvider({ children }) {return (<ThemeProvider><UserProvider><SettingsProvider>{children}</SettingsProvider></UserProvider></ThemeProvider>);
}
5. 常见问题和解决方案
5.1 避免重渲染
// 使用 useMemo 优化 Context value
function ThemeProvider({ children }) {const [theme, setTheme] = useState('light');const value = useMemo(() => ({theme,toggleTheme: () => setTheme(t => t === 'light' ? 'dark' : 'light')}), [theme]);return (<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>);
}
5.2 处理嵌套 Context
// 创建组合 Provider
function AppProviders({ children }) {return (<AuthProvider><ThemeProvider><UserProvider>{children}</UserProvider></ThemeProvider></AuthProvider>);
}// 使用组合 Provider
function App() {return (<AppProviders><MainApp /></AppProviders>);
}
6. 总结
6.1 使用场景
- 主题切换
- 用户认证状态
- 语言偏好
- 全局配置
- 路由状态共享
6.2 最佳实践建议
- 适度使用 Context
- 创建专门的 Provider 组件
- 使用自定义 Hook 封装 Context 逻辑
- 注意性能优化
- 合理组织 Context 结构