0Pricing
Frontend Academy · 课时

使用 useContext 管理全局状态

创建 Context,使用 Provider 包裹子树,并通过 useContext 使用其值,在无需逐层传递属性的情况下共享主题或身份验证状态。

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

属性逐层传递的问题

属性逐层传递是指数据需要经过许多不使用它的中间组件,才能传递给深层嵌套的子组件。上下文通过让树中的任何组件都能访问某个值来解决这个问题,无需显式地逐层传递。

创建上下文

createContext(defaultValue) 会创建一个上下文对象。当组件读取上下文但上方没有匹配的提供者时,就会使用默认值。

import { createContext } from 'react';

interface ThemeContextType {
  theme: 'light' | 'dark';
  toggleTheme: () => void;
}

const ThemeContext = createContext<ThemeContextType>({
  theme: 'light',
  toggleTheme: () => {}
});

提供上下文

用提供者包裹树中需要该上下文的部分。内部的所有组件都可以读取上下文值。

function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');

  const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');

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

// In app root:
<ThemeProvider>
  <App />
</ThemeProvider>

使用 useContext 获取上下文

提供者内部的任何组件都可以通过 useContext(ThemeContext) 获取上下文值。无需将任何内容作为属性传递。

function ThemeToggle() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <button onClick={toggleTheme}>
      Switch to {theme === 'light' ? 'dark' : 'light'} mode
    </button>
  );
}

使用自定义钩子封装 useContext

导出一个内部调用 useContext 的自定义钩子。这样比直接暴露上下文更简洁,还可以添加验证。

function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
  return ctx;
}

// Usage:
const { theme } = useTheme();

上下文重新渲染

当提供者的值发生变化时,所有消费者都会重新渲染。如果该值是对象,那么每次渲染都创建新的对象引用会导致所有消费者重新渲染。请使用 useMemo 记忆化该值,以避免这种情况。

const value = useMemo(
  () => ({ theme, toggleTheme }),
  [theme] // toggleTheme is stable if created with useCallback
);

<ThemeContext.Provider value={value}>

何时使用上下文

适合用于:主题、区域设置、已认证用户、功能开关、通知系统。不太适合用于:高频更新(每次按键都更新)、大型复杂状态(请改用状态管理库)。

多个上下文

您可以拥有多个相互独立的上下文。请让它们各司其职——使用 AuthContext 处理身份验证,使用 ThemeContext 处理主题。避免创建一个包含所有内容的万能上下文。

上下文与 Redux

上下文是内置功能,足以处理不经常变化的全局数据。Redux/Zustand/Pinia 更适合处理更新频繁的复杂状态、需要时间旅行调试或需要中间件的场景。

身份验证上下文模式

一种常见模式是:使用 AuthContext 保存当前用户和身份验证方法。使用该上下文的组件无需逐层传递属性即可获取用户信息。

interface AuthContext {
  user: User | null;
  login: (creds: Credentials) => Promise<void>;
  logout: () => void;
}
const AuthCtx = createContext<AuthContext | null>(null);
export const useAuth = () => {
  const ctx = useContext(AuthCtx);
  if (!ctx) throw new Error('Outside AuthProvider');
  return ctx;
};

上下文与 TypeScript

使用接口为上下文声明类型。将 null 作为初始值,并在自定义钩子检测到该值为 null 时抛出错误。这样可以避免“在提供者外部使用上下文”这一不可能的状态被静默忽略。

性能:memo 与上下文

使用 React.memo 包装的组件只有在属性发生变化时才会重新渲染。如果上下文消费者的输出只依赖上下文的一部分,请拆分上下文或使用选择器模式,以避免不必要的重新渲染。

快速检查

在一个上方没有提供者的组件中调用 useContext(MyContext) 时,它会返回什么?

总结:useContext

createContext 会使用默认值创建上下文。使用提供者包装组件树,以提供一个值。在提供者内部的任何位置,都可以使用 useContext 读取该值。自定义钩子可以封装 useContext 以进行验证。请记忆化提供者的值,以避免不必要的重新渲染。它适合用于主题和身份验证等不经常变化的全局数据。

常见问题解答

「使用 useContext 管理全局状态」课时是免费的吗?

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

「使用 useContext 管理全局状态」这节课中我会学到什么?

创建 Context,使用 Provider 包裹子树,并通过 useContext 使用其值,在无需逐层传递属性的情况下共享主题或身份验证状态。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Frontend Academy 需要有经验吗?

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

「使用 useContext 管理全局状态」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. 使用 useContext 管理全局状态
  2. 使用 useReducer 管理复杂状态
  3. 使用 useMemo 与 useCallback 提升性能
  4. 自定义 Hook:提取可复用逻辑
← 返回 Frontend Academy