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

相关推荐
hongkid5 分钟前
React Native 如何打包正式apk
javascript·react native·react.js
李少兄8 分钟前
简单讲讲 SVG:前端开发中的矢量图形
前端·svg
前端小万9 分钟前
告别 CJS 库加载兼容坑
前端·前端工程化
恋猫de小郭9 分钟前
Flutter 3.38.1 之后,因为某些框架低级错误导致提交 Store 被拒
android·前端·flutter
JarvanMo13 分钟前
Flutter 需要 Hooks 吗?
前端
光影少年23 分钟前
前端如何虚拟列表优化?
前端·react native·react.js
Moment25 分钟前
一杯茶时间带你基于 Yjs 和 reactflow 构建协同流程图编辑器 😍😍😍
前端·后端·面试
菩提祖师_39 分钟前
量子机器学习在时间序列预测中的应用
开发语言·javascript·爬虫·flutter
invicinble43 分钟前
对于前端数据的生命周期的认识
前端
PieroPc1 小时前
用FastAPI 后端 和 HTML/CSS/JavaScript 前端写一个博客系统 例
前端·html·fastapi