React 中 createContext 和 useContext 的深度应用与优化实战

文章目录

一.前置知识

  1. createContext简介
    • createContext是 React 提供的一个用于创建上下文(Context)的函数。上下文是一种在组件树中共享数据的方式,它允许你将数据传递给多个组件,而不必通过组件树的每一层手动传递props。这在处理一些全局状态(如主题、用户认证信息等)时非常有用。
    • 当你调用createContext时,它会返回一个包含两个属性的对象:ProviderConsumer(在使用函数组件和useContext钩子时,Consumer的使用方式被简化了)。Provider是一个组件,用于提供数据给它的后代组件;Consumer是一个用于订阅Provider提供的数据的组件(在使用useContext时这个过程更简单)。
  2. useContext简介
    • useContext是一个 React 钩子,它用于在函数组件中订阅由createContext创建的上下文。通过useContext,函数组件可以轻松地访问到在组件树中上层Provider组件提供的数据,使得在组件树中共享数据变得更加方便和简洁。
    • 它接收一个上下文对象(由createContext创建的)作为参数,并返回该上下文的当前值。这样,组件就可以根据这个值来进行渲染或其他操作。

二.代码实现

目录结构

js 复制代码
|------ pages
|------------ ContentProVider
|--------------------- index.jsx
|--------------------- ContentProvider.jsx
|--------------------- one.jsx
|--------------------- two.jsx
|--------------------- three.jsx
|--------------------- four.jsx
|--------------------- five.jsx

1.创建ContentProvider组件

ContentProvider.jsx

封装 createContextuseContext使用

jsx 复制代码
// 引入 React 的 createContext 和 useContext 方法,以及 useState 钩子
import { createContext, useContext, useState } from 'react'

// 创建一个 EventContext 的上下文对象,初始值为空对象
const EventContext = createContext({})

/**
 * useEventContext 是一个自定义钩子,用于获取 EventContext 的当前值。
 */
export const useEventContext = () => useContext(EventContext)

/**
 * ContentProvider 是一个组件,用于提供 EventContext 的值。
 * 这个组件提供为了封装 EventContext 的值,并且可以在整个组件中共享。
 */
export const ContentProvider = ({ children }) => {
  const [count, setCount] = useState(0)
  const [data, setData] = useState('null')

  //  updateData 是一个函数,用于更新 data 状态变量的值为当前时间戳。
  const updateData = () => {
    setData(new Date().getTime())
  }

  return (
    // 使用 EventContext.Provider 组件提供 count、setCount、data 和 updateData 的值
    <EventContext.Provider
      value={{
        count,
        setCount,
        data,
        updateData
      }}
    >
      {children}
    </EventContext.Provider>
  )
}

2.使用封装的ContentProvider组件 + useEventContext钩子函数

顶层组件

jsx 复制代码
import { useEventContext, ContentProvider } from './ContentProvider'
import OnePage from './one'

/**
 * CreateContent 组件作为顶层组件使用
 * 使用 useEventContext 钩子函数来获取上下文数据和方法,在页面上显示和操作这些数据。
 */
const CreateContent = () => {
  // 使用 useEventContext 钩子函数获取上下文数据和方法
  const { count, setCount, data, updateData } = useEventContext()
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <div style={{ borderBottom: '1px solid black', marginBottom: 10, paddingBottom: 10 }}>
        {count}
        <h1>{count}</h1>
        <button onClick={() => setCount(count + 1)}>{count}</button>
      </div>

      <div onClick={() => updateData()}>更新数据</div>
      <div>{data}</div>
      <hr />
      <div style={{ marginLeft: 25 }}>
        <OnePage />
      </div>
    </div>
  )
}

/**
 * CreateContentPage 组件是一个 React 函数组件,用于创建内容页面。
 * 它使用 ContentProvider 组件来提供上下文,并在其内部渲染 CreateContent 组件。
 *
 * @returns {JSX.Element} 返回一个包含 CreateContent 组件的 JSX 元素。
 */
const CreateContentPage = () => {
  // 使用 ContentProvider 组件来提供上下文
  return (
    <ContentProvider>
      <CreateContent />
    </ContentProvider>
  )
}

export default CreateContentPage

3.嵌套层级的函数组件 (这部分意义不大,只是为了展示嵌套层级)

jsx 复制代码
// one.jsx
import TwoPage from './two'
/**
 * OnePage 组件用来嵌套组件,用于展示第一层子组件。
 * 展示一个标题和一个嵌套的 TwoPage 组件。
 */
const OnePage = () => {
  return (
    <div>
      <h1>第一层子组件</h1>
      <div style={{ marginLeft: 25 }}>
        {/* 渲染 TwoPage 组件 */}
        <TwoPage />
      </div>
    </div>
  )
}

export default OnePage
jsx 复制代码
// two.jsx
import ThreePage from './three'
const TwoPage = () => {
  return (
    <div>
      <h1>第二层子组件</h1>
      <div style={{ marginLeft: 25 }}>
        <ThreePage />
      </div>
    </div>
  )
}

export default TwoPage
jsx 复制代码
// three.jsx
import FourPage from './four'
const ThreePage = () => {
  return (
    <div>
      <h1>第三层子组件</h1>
      <div style={{ marginLeft: 25 }}>
        <FourPage />
      </div>
    </div>
  )
}

export default ThreePage
jsx 复制代码
import FivePage from './five'

const FourPage = () => {
  return (
    <div>
      <h1>第四层子组件</h1>
      <div style={{ marginLeft: 25 }}>
        <FivePage />
      </div>
    </div>
  )
}
export default FourPage

4.最底层的函数组件

jsx 复制代码
// 导入 useEventContext 钩子
import { useEventContext } from './ContentProvider'

/**
 * FivePage 组件是最底部组件,用于展示和更新上下文数据。
 * 使用 useEventContext 钩子来获取上下文数据,并在页面上展示和更新这些数据。
 *
 */
const FivePage = () => {
  // 使用 useEventContext 钩子获取上下文数据
  const { count, setCount, data } = useEventContext()
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <div style={{ borderBottom: '1px solid black', marginBottom: 10, paddingBottom: 10 }}>
        {count}
        <h1>{count}</h1>
        {/* 点击按钮增加 count 的值 */}
        <button onClick={() => setCount(count + 1)}>{count}</button>
      </div>

      <div>{data}</div>
      <hr />
    </div>
  )
}

export default FivePage

三.效果展示



四.总结

通过对 React 中 createContext 和 useContext 的深入学习和实践,我们能够有效地在组件树中共享数据,避免了繁琐的 props 层层传递。在实际应用中,合理地使用上下文可以提高代码的可维护性和可读性,尤其是在处理全局状态或需要在多个组件间共享的数据时。同时,通过对代码的优化,我们进一步提升了性能和代码质量,使得应用在运行时更加高效和稳定。

相关推荐
小桥风满袖8 分钟前
极简三分钟ES6 - ES9中对象扩展
前端·javascript
云舟吖16 分钟前
基于 electron-vite 实现一个 RPA 网页自动化工具
前端·架构
用户94818176754419 分钟前
超越NAT:如何构建高效、安全的内网穿透隧道
前端
明天的明22 分钟前
vue双向数据绑定失效
前端
bug_kada25 分钟前
前端路由:深入理解History模式
前端·面试
LIUENG26 分钟前
快速开发一个 VSCode 插件
前端·visual studio code
bug_kada27 分钟前
前端路由:Hash vs History,一篇讲明白!
前端·面试
城中的雾27 分钟前
HarmonyOS应用拉起系列(三):如何直接拉起腾讯/百度/高德地图进行导航
前端·javascript·harmonyos
李明卫杭州30 分钟前
CSS 中 nth-child 选择器的详细用法和示例
前端
会豪30 分钟前
CSS 动画属性精讲:从基础到实战
前端·css