React Context用法总结

news/2025/1/11 2:41:02/

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 使用场景

  1. 主题切换
  2. 用户认证状态
  3. 语言偏好
  4. 全局配置
  5. 路由状态共享

6.2 最佳实践建议

  1. 适度使用 Context
  2. 创建专门的 Provider 组件
  3. 使用自定义 Hook 封装 Context 逻辑
  4. 注意性能优化
  5. 合理组织 Context 结构

http://www.ppmy.cn/news/1562132.html

相关文章

HTML - <script>,<noscript>

<script>标签用于在网页插入脚本&#xff0c;<noscript>标签用于指定浏览器不支持脚本时的显示内容。 1.<script> <script>用于加载脚本代码&#xff0c;目前主要是加载 JavaScript 代码。 <script> console.log(hello world); </script&g…

基于单片机的公交车报站系统设计

摘 要 目前&#xff0c;我国经济快速发展&#xff0c;城市化进程不断加快。公交车作为居民日常出行的重要交通工具&#xff0c;公交车的服务质量直接影响到乘客的乘车体验&#xff0c;关系到城市智能交通的发展。为了解决传统公交车上车载终端信息闭塞的问题&#xff0c;提高公…

基于springboot的课程作业管理系统源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的课程作业管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 可以管理首页、个人中心…

BI结合数据分析系统,为企业发展提供坚实的保障

BI商业智能结合数据分析是一个复杂而系统的过程&#xff0c;它涉及数据的收集、处理、分析和呈现等多个环节。数聚就从多年的部署实施经验来详细的阐述BI如何结合数据分析系统&#xff0c;是如何为企业发展奠定基础的。 一、数据集成与清洗 数据集成&#xff1a;BI系统首先需要…

TR-069协议学习--Soap报文、事件、RPC方法

目录 一、SOAP报文 二、事件 三、RPC方法 四、错误码 一、SOAP报文 SOAP&#xff08;Simple Object Access Protocol&#xff0c;简单对象访问协议&#xff09;是一种基于XML的协议&#xff0c;用于在网络上交换结构化信息。SOAP报文是SOAP协议中用于传输数据的XML文档…

2025新年源码免费送

2025很开门很开门的源码免费传递。不需要馒头就能获取4套大开门源码。 听泉偷宝&#xff0c;又进来偷我源码啦&#x1f44a;&#x1f44a;&#x1f44a;。欢迎偷源码 &#x1f525;&#x1f525;&#x1f525; 获取免费源码以及更多源码&#xff0c;可以私信联系我 我们常常…

C++二十三种设计模式之抽象工厂模式

C二十三种设计模式之抽象工厂模式 一、组成二、特点三、目的四、缺点五、示例代码 一、组成 抽象产品类&#xff1a;声明产品功能公共接口。 具体产品类&#xff1a;实现产品功能接口。 抽象工厂类&#xff1a;声明创建一组具体产品公共接口。 具体工厂类&#xff1a;实现创建…

Linux开发工具(补充)

Git git仓库本质上是一个目录&#xff0c;.gitignore文件里对应文件后缀不会被上传 下载指令 sudo yum install git 提交方法 下载项目到本地 创建好一个放置代码的目录. git clone [url] 这里的 url 就是刚刚建立好的项目的链接. 三板斧第一招: git add 将代码放到刚才下…