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 层层传递。在实际应用中,合理地使用上下文可以提高代码的可维护性和可读性,尤其是在处理全局状态或需要在多个组件间共享的数据时。同时,通过对代码的优化,我们进一步提升了性能和代码质量,使得应用在运行时更加高效和稳定。

相关推荐
安晴晚风1 小时前
从0开始在linux服务器上部署SpringBoot和Vue
linux·运维·前端·数据库·后端·运维开发
前端小小王2 小时前
pnpm、Yarn 和 npm 的区别?
前端·npm·node.js
supermapsupport2 小时前
使用npm包的工程如何引入mapboxgl-enhance/maplibre-gl-enhance扩展包
前端·webpack·npm·supermap·mapboxgl
牛奔2 小时前
windows nvm 切换node版本后,npm找不到
前端·windows·npm·node.js
鱼大大博客2 小时前
Edge SCDN酷盾安全重塑高效安全内容分发新生态
前端·安全·edge
鸭梨山大。2 小时前
NPM组件包 vant部分版本内嵌挖矿代码
前端·安全·npm·node.js·vue
蟾宫曲7 小时前
在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
前端·npm·vue3·vite·element-plus·计时器
秋雨凉人心7 小时前
简单发布一个npm包
前端·javascript·webpack·npm·node.js
liuxin334455667 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
qq13267029407 小时前
运行Zr.Admin项目(前端)
前端·vue2·zradmin前端·zradmin vue·运行zradmin·vue2版本zradmin