React"隔空取物"-useContext 用起来就这么简单

69 阅读5分钟

引言

最近小编也是在学习React的路上越走越远,并且来到了useContext,让大家跟随小编的脚步,一步一个脚印,学习React的隔空取物API-Context
假设你正在开发一个后台管理系统,有一个全局主题配置需要传递给多个嵌套组件。如果使用 props 一层层传递,代码冗余、维护困难。 那么有没有一种方式可以像“隔空取物”一样,直接获取到顶层的数据?

本文将详细介绍useContext的使用方式、适用场景以及最佳实践。


Context API是什么?

邻里叔叔阿姨想要拿到变量时使用useContextContext APIReact 提供的一种机制,用于在组件树中共享数据(如状态、配置、主题等),而不需要手动通过 props 一层层传递。换句话说:

Context 让你绕过中间组件,直接将数据“广播”给任意深层的子组件。


💻看下实际代码吧

项目结构分析

src/
|── App.jsx      # 根组件
|── ThemeContext.js  # 主题上下文
|── main.jsx     # 应用入口
|── components/
    |── Child/
        |── index.jsx  # 子组件
    |── Page/
        |── index.jsx  # 页面组件
|── hooks/       # 自定义钩子

如何理解ThemeContext

在使用Hooks自定义函数之前我们需要理解ThemeContext在全局文件下创建的作用。很多组件都需要应用到该组件,这是React中实现跨组件共享状态的推荐方式之一,特别适合像主题这样需要全局使用的数据。

// 主题 适合全局
import { createContext} from 'react'
export const ThemeContext = createContext("light")

让我们在App组件当中打印看看ThemeContext的内容

image.png

App当中引用

在组件树的某个父级位置使用<ThemeContext.Provider>来提供上下文位置。

import { useState } from 'react'
import './App.css'
import Page from './components/Page'
import { ThemeContext } from './ThemeContext'

function App() {
  const [theme, setTheme] = useState("light");
  // console.log(ThemeContext);

  return (
    <ThemeContext.Provider value={theme}>
      <Page />
      <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>Change Theme</button>
    </ThemeContext.Provider>
  )
}

export default App

网页文章修改.gif

封装Hooks效果

现在我们需要自定义一个Hooks然后封装一个Hooks内容函数,让我们来看看下面所写代码的作用。

// 自定义hooks
// hooks + component renderer
import { useContext } from 'react';
import { ThemeContext } from '../ThemeContext';

export function useTheme(){
  return useContext(ThemeContext)

}
  1. 封装上下文消费逻辑:它将useContext(ThemeContext)的调用封装起来,使组件代码更加简洁

  2. 简化导入路径:组件不需要了解ThemeContext的导入路径,只需导入useTheme

组件代码从:

import { useContext } from "react"
import { ThemeContext } from "@/ThemeContext"

const Child = () => {
  const theme = useContext(ThemeContext)

简化为:

import { useTheme } from "@/hooks/useTheme"
const Page = () => {
  const theme = useTheme()

这种简化不仅减少了样板代码,还提高了代码的可测试性和可维护性。

为此我们分别用两种方式来写子组件Page的代码和Page子组件Child的两个组件代码,让我们直观地来看一下这两种写法在页面效果和代码书写规范上的区别。

子组件Page

import Child from "../Child"
import { useTheme } from "@/hooks/useTheme"
const Page = () => {
  const theme = useTheme()
  return (
    <>
      {theme}
      <Child />
    </>
  )
}

export default Page

Page子组件Child

import { useContext } from "react"
import { ThemeContext } from "@/ThemeContext"
// use
// 函数
// 响应式状态和生命周期
// 很好用
const Child = () => {
  const theme = useContext(ThemeContext)
  return (
    <div className={theme}>
      Child {theme}
    </div>
  )
}


export default Child

实现效果

theme.gif

开发当中应用场景

下面我将为你列举 3 个 useContext 的实际应用场景,并且对于每个实际开发应用场景当中用 简洁清晰的代码示例 和说明。这些场景都来自于真实项目中常见的需求,适合初中级 React 开发者理解和应用。


✅ 实际应用场景一:全局主题(Theme)管理

场景描述:

在网站或管理系统中,用户可以选择“深色”或“浅色”主题,这个主题信息需要被多个层级组件使用,比如按钮、标题等。

示例代码:

// ThemeContext.js
import React from 'react';

const ThemeContext = React.createContext();
export default ThemeContext;

App组件当中根父组件向子组件传值<ThemeContext.Provider value={theme}>

// App.js
import React, { useState } from 'react';
import ThemeContext from './ThemeContext';
import Header from './Header';

function App() {
  const [theme] = useState({
    background: '#222',
    color: '#fff'
  });

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

// Header.js
import React from 'react';
import ThemeContext from './ThemeContext';

function Header() {
  const theme = React.useContext(ThemeContext);

  return (
    <header style={{ background: theme.background, color: theme.color }}>
      我是主题头部
    </header>
  );
}

✅ 实际应用场景二:用户登录状态共享

场景描述:

用户登录后,需要在整个应用中显示用户名、头像、权限等信息,这时可以用 Context 来共享用户状态。

示例代码:

// AuthContext.js
import React from 'react';

const AuthContext = React.createContext();
export default AuthContext;

// App.js
import React, { useState } from 'react';
import AuthContext from './AuthContext';
import Profile from './Profile';

function App() {
  const [user] = useState({ name: '张三', role: 'admin' });

  return (
    <AuthContext.Provider value={user}>
      <Profile />
    </AuthContext.Provider>
  );
}

// Profile.js
import React from 'react';
import AuthContext from './AuthContext';

function Profile() {
  const user = React.useContext(AuthContext);

  return (
    <div>
      <h2>欢迎回来,{user.name}</h2>
      <p>你的角色是:{user.role}</p>
    </div>
  );
}

React Context 的注意事项

1. 避免频繁更新 Context 的值

  • ❗️如果 Context 的 value 经常变化,可能会导致所有使用该 Context 的组件频繁重新渲染。
  • ✅建议:用 useMemo 包裹 value,防止不必要的重渲染。
深色版本
const value = React.useMemo(() => ({ theme, updateTheme }), [theme]);
<ThemeContext.Provider value={value}>

2. 不要滥用 Context

  • ❗️把所有状态都放进 Context 会降低组件的可维护性和可测试性。
  • ✅建议:只在需要跨层级共享的状态或配置中使用 Context。

3. 默认值只在没有 Provider 时生效

  • ❗️如果你忘记包裹 <MyContext.Provider>,那么 useContext 返回的是创建 Context 时传入的默认值。
  • ✅建议:开发阶段设为 undefined 或抛出错误,帮助发现问题

总结:useContext 的使用场景

应用场景是否推荐
主题配置✅ 推荐
用户信息✅ 推荐
多语言支持✅ 推荐
表单配置✅ 推荐
高频状态更新❌ 不推荐(考虑 Redux 或优化)
复杂业务逻辑❌ 不推荐(考虑 Redux Toolkit)