0Pricing
React Academy · 课时

使用 React Context 管理主题状态

构建 ThemeProvider,将当前主题和切换函数提供给整个组件树

使用 React Context 管理主题状态 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

创建 ThemeContext

首先,调用 createContext(),传入与上下文结构匹配的默认值:const ThemeContext = createContext({ theme: 'light', toggleTheme: () => {} })。仅当组件在没有父级提供者的情况下读取上下文时,才会使用默认值;这有助于测试独立组件。

ThemeProvider 组件

ThemeProvider 组件是一个包装组件,包含所有主题逻辑。它在挂载时读取系统偏好设置,管理 theme 状态,提供 toggleTheme 函数,并将子组件包装在 ThemeContext.Provider value={{ theme, toggleTheme }} 中。请将它放在组件树靠近顶部的位置。

通过 useContext 使用上下文

任何后代组件都可以通过调用 useContext(ThemeContext) 来访问主题。它会返回当前上下文值,其中包括 theme 和 toggleTheme。主题发生变化时,组件会自动重新渲染,因此始终保持同步,无需逐层传递属性。

将 data-theme 同步到 DOM

CSS 变量依赖根元素上的 data-theme 属性。在 ThemeProvider 中添加一个 useEffect,使其在 theme 发生变化时运行:document.documentElement.setAttribute('data-theme', theme)。这样可以无缝连接 React 状态和 CSS 层。

将用户覆盖设置存储到 localStorage

为了让用户的选择在页面重新加载后仍然保留,请在主题发生变化时写入 localStorage:localStorage.setItem('theme', theme)。您可以将这段逻辑封装在自定义的 useLocalStorage 钩子中;它返回一对类似状态的值,并自动持久化每次更新。

从 localStorage 初始化主题

初始化主题状态时,请先从 localStorage 读取:localStorage.getItem('theme')。如果不存在已存储的值,则通过 window.matchMedia('(prefers-color-scheme: dark)').matches 回退到系统偏好设置。此初始化只会在挂载时运行一次。

主题优先级顺序

正确的优先级顺序从高到低是:localStorage 中存储的用户偏好设置、系统 OS 偏好设置,最后是硬编码的默认值(通常为浅色)。这种顺序确保用户始终拥有最终控制权;如果用户尚未在应用中明确选择主题,也会继续遵循其 OS 配置。

useTheme 便捷钩子

如果在每个组件中直接调用 useContext(ThemeContext),就会暴露实现细节。相反,请导出一个 useTheme 钩子:function useTheme() { return useContext(ThemeContext); }。这样,组件只需导入并调用 useTheme,无需了解底层上下文。

提供切换函数

toggleTheme 函数会在浅色和深色之间切换:setTheme(prev => prev === 'light' ? 'dark' : 'light')。请通过上下文公开它,这样组件树中的任何按钮都可以触发它。状态集中存放,切换逻辑则在各处共享。

记忆化上下文值

每次 ThemeProvider 重新渲染时,都会重新创建上下文值对象。请使用 useMemo 包装它,以避免所有上下文使用组件不必要地重新渲染:const value = useMemo(() => ({ theme, toggleTheme }), [theme])。这是上下文提供者常用的性能优化方式。

测试 ThemeProvider

在测试中,请使用自定义的 renderWithTheme 工具包装渲染,并将 ThemeProvider 作为包装器。您也可以创建一个轻量的模拟上下文,以便独立测试:ThemeContext.Provider value={{ theme: 'dark', toggleTheme: jest.fn() }}。这样就可以在指定的主题状态下测试组件。

主题优先级顺序

初始化应用主题时,正确的优先级顺序(从高到低)是什么?

课程回顾:使用 React 上下文管理主题状态

创建一个 ThemeContext 和一个 ThemeProvider,用于管理主题状态、同步到 localStorage,并在文档上设置 data-theme。使用 useTheme 便捷钩子来简洁地使用主题。优先级顺序是:已存储的偏好设置、系统偏好设置,最后是默认值。

常见问题解答

「使用 React Context 管理主题状态」课时是免费的吗?

是的 — 「使用 React Context 管理主题状态」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「使用 React Context 管理主题状态」这节课中我会学到什么?

构建 ThemeProvider,将当前主题和切换函数提供给整个组件树 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「使用 React Context 管理主题状态」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 检测系统配色方案
  2. 用于主题切换的 CSS 变量
  3. 使用 React Context 管理主题状态
  4. 持久化主题并防止闪烁
← 返回 React Academy