hook之useContext

2023-05-16

useContext这个hook,我们通过翻译就可以大致知道它的用途,译为使用上下文。context上下文我们在前面就已经使用过了,它是一种用于跨组件之间的传值的技术。

我们学过Context,再来学习useContext这个hook就会变得简单很多。

useContex的作用

一句话来说,就是获取当前引入组件的上下文对象。

useContex的写法

const ctx=useContext(参数)

//useContext只接收一个参数,为我们引入的由React.createContext函数生成的一个上下文对象;

其返回值就是这个上下文对象provider时提供的数据;

注意:一旦在某个组件里面使用了useContext这就相当于该组件订阅了这个context上下文对象的变化,当context值发生变化时,使用到该context的子组件就会被触发重渲染,且它们会拿到context的最新值。

思考为什么要引入useContex?

我们写一个例子:

先定义一个context上下文对象:

import React from 'react'
let myctx=React.createContext()
export default myctx;

在父组件中提供数据:

import React,{useState,useEffect} from 'react'
import Myctx from './myctx'
import Box4 from './Box4'
function App() {  
let [obj,setObj]=useState({a:1,b:2})
  return ( 
    <div className="App">   
      <Myctx.Provider value={obj}>
            <Box4></Box4>
      </Myctx.Provider>
    </div>
  ); 
}

在子组件中获取数据:

import React from 'react'
import Myctx from './myctx'
export default function Box4() {

  return (
    <div>
        <Myctx.Consumer>
        
        {
            (data)=>{
                return (
                    <div>
                        box4----------------
                     <div>{data.a}</div>
                    <div>{data.b}</div>
                    </div>
                 
                )
            }
        }
        </Myctx.Consumer>
    </div>
  )
}

在Box4中确确实实获取到了app组件提供的数据,但是只能在在模板中操作数据,不能在外部做一些操作,因此提供了useContext让我们可以在模板外获取到父组件提供的数据。

在Box4组件中使用useContext,改进代码:

import React from 'react'
import Myctx from './myctx'
export default function Box4() {
    let obj=useContext(Myctx)
    console.log(obj);
  return (
    <div>
        <Myctx.Consumer>
        
        {
            (data)=>{
                return (
                    <div>
                        box4----------------
                     <div>{data.a}</div>
                    <div>{data.b}</div>
                    </div>
                 
                )
            }
        }
        </Myctx.Consumer>
    </div>
  )
}

 可以在控制台看到接受的数据:

 

解决使用useContext()时产生的无效渲染

我们在app组件中能够传数据,也可以把该属性的修改方法也传递过去,如:

let [obj,setObj]=useState({a:1,b:2})

---------------------------------------------

<Myctx.Provider value={[obj,setObj]}>

            <Box4></Box4>

      </Myctx.Provider>

 在Box4中接收,

let [obj,setObj]=useContext(Myctx)

 即我们可以在Box4中修改父组件提供的数据,如:

import React, { useContext } from 'react'
import Myctx from './myctx'
export default function Box4() {
    let [obj,setObj]=useContext(Myctx)
    // console.log(obj,setObj);
    obj.a=11
    setObj({...obj})
  return (
    <div>
        {obj.a}
    </div>
  )
}

通过useContext我们更加方便的获取context对象的数据,但是实际开发中我们可能会把很多不同的数据放在同一个context里面,而不同的子组件可能只关心这个context的某一部分数据,当context里面的任意值发生变化的时候,无论这些组件用不用到这些数据它们都会被重新渲染,这可能会造成一些性能问题.

就比如现在我在Box4中,只用到了提供的对象的a属性,但是当我修改b属性时Box4组件也会从新渲染。

这里提供两种解决无效渲染的方法

1、拆分Context

这个方法是最被推荐的做法,和useState一样,我们可以将不需要同时改变的context拆分成不同的context,让它们的职责更加分明,这样子组件只会订阅那些它们需要订阅的context从而避免无用的重渲染。

比如我们把obj拆分为两个对象,{a:1,b:2}=>{a:1}、{b:2}

然后分别创建两个上下文存储,

actx上下文:

import React from 'raeact'
let actx=React.createContext()
export default actx;

bctx上下文:

import React from 'raeact'
let bctx=React.createContext()
export default bctx;

在提供数据时,要同时提供两个上下文的写法采用嵌套写法:

<Actx.Provider value={[obj,changeObj]}>
       <Bctx.Provider value={[car,changecar]}>
          <Box4></Box4>
       </Bctx.Provider>
    </Actx.Provider>

即在box4中获取时,只接收Actx就行了,当其它组件中接收Bctx修改b的值,box4组件不会受到影响。

2、可以使用useMemo来优化

useMemo可以缓存任何类型的数据,我们将整个组件函数缓存起来,将组件中所使用到的数据设置为依赖项,只有当所依赖的数据发生改变时才从新渲染。

如:

import React,{useContext,useMemo} from 'react'
import Box2 from "./Box2.jsx"
import userctx from './ctx/userctx.jsx'
function MyMemoBox2(){
  let [user,changeuser]=useContext(userctx)
  let Box1=()=>{
    return (<div>
          <div>{user.user.a}</div>
          <Box2></Box2>
         </div>)
  }
  return useMemo(Box1,[user.user])
}
export default MyMemoBox2

即只有当user中的user发生改变时才会从新渲染该组件,在其它使用该上下文的组件中修改了user的其它属性不会对Box1组件造成影响。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hook之useContext 的相关文章

  • IOS越狱如何拦截短信/短信

    我目前正在尝试编写一个应用程序来拦截文本消息并根据该消息的内容做出反应 我试图挂钩 receivedMessage struct CKSMSRecord message replace BOOL replaceCKSMSService 类中
  • WH_MOUSE 和 WH_MOUSE_LL 挂钩之间有哪些区别?

    我发现WH MOUSE并不总是被调用 问题可能是我正在使用WH MOUSE并不是WH MOUSE LL 代码 class MouseHook public static signal
  • 如何添加在所有 cron 作业之前运行的 pre-hook 和 post-hook 脚本?

    假设我有以下 cron 条目 bin date 现在假设我想要在 cron 作业运行之前和之后运行的脚本 我可以将 cron 条目修改为如下所示 bin prehook bin date bin posthook 或者 如果我想要 preh
  • 使用 useState 和 useContext React Hooks 持久化 localStorage

    我已经设置了一个提供程序来为用户共享一些状态useContext 因此 我试图利用本地存储来保存用户图像 头像等 的一些状态 首先 我尝试保留用户的头像 本质上是从 Express 中保存他们的 ID 然后在调用 Cloudinary 一种
  • 低级键盘挂钩

    我刚刚买了一个新键盘 我有兴趣准确跟踪键盘整个使用寿命期间我按下 敲击的次数 我只想记录 keyUp 因为我不关心重复 我一直在搜索最好的方法来做到这一点 但我什至不知道该采取什么方法 所以我在智能搜索方面遇到了困难 另外 我真正使用过的唯
  • SpecFlow - 重试失败的测试

    有没有办法实现AfterScenario在失败的情况下重新运行当前测试的钩子 像这样的东西 AfterScenario retry public void Retry if ScenarioContext Current TestError
  • C++ d3d hooking - COM vtable

    尝试制作一个 Fraps 类型的程序 请参阅评论以了解失败的地方 include precompiled h typedef IDirect3D9 STDMETHODCALLTYPE Direct3DCreate9 t UINT SDKVe
  • PyInstaller 2.1导入自定义包

    我有一个脚本正在尝试使用 Python 2 7 使用 PyInstaller 2 1 进行编译 该脚本使用我编写的名为 auto common 的自定义包 在脚本中 我使用以下命令导入它 sys path append path to pa
  • 连接 Hibernate 的查询生成

    我想实施虚拟视图与预处理器 一个简单的例子 之前的HQL FROM PublishedArticle a 生效后的 HQL FROM Article a WHERE a published true 本质上 我需要一种在执行查询之前处理查询
  • 从活动顶点数组生成平滑法线

    我正在尝试通过挂钩 OpenGl 调用来破解和修改旧版 opengl 固定管道游戏的多个渲染功能 而我当前的任务是实现着色器照明 我已经创建了一个适当的着色器程序 可以正确照亮大部分对象 但该游戏的地形是在没有提供正常数据的情况下绘制的 游
  • 如何在Windows平台上编写Git Server Hooks?

    我找不到任何适用于 Windows 的 Git 挂钩的明确示例 我在 Windows Server 上使用 Bonobo Git Server 我需要预提交和提交后挂钩作为 cmd 或 bat 预提交应检查空注释 提交后应发送有关提交的电子
  • 全局键盘挂钩的合法用途是什么?

    除了仅应由操作系统提供的应用程序启动快捷方式之外 Windows 键盘挂钩等东西的合法用途是什么 在我看来 我们只在键盘记录器之类的事情上遇到问题 因为操作系统提供了钩子来执行除操作系统内核本身之外的任何情况下任何人都不允许执行的操作 编辑
  • 低级挂钩/SetWindowsHookEx lParam 自动重复?

    在这里阅读 Windows PC 上如何实现键盘自动重复 https stackoverflow com questions 876852 how is keyboard auto repeat implemented on a windo
  • 删除 woocommerce 店面主页标题 php

    我正在使用 woocommerce 的店面主题 我需要用 php 删除主页标题 h1 我知道 css 解决方案 但我不想使用它 因为我想将 h1 添加到该页面的其他位置 并且在一个页面中包含 2 个 h1 对 seo 不利页 我也知道删除页
  • Git Hook - 在我推送到 github 后让服务器拉取

    我有一个本地存储库 并且我在实时服务器上设置了另一个存储库 www site com projects ProjectA 我想要实现的目标非常简单 在我推送到 GitHub 后 我想要存储库位于www site com projects P
  • git Push Remote:警告:hooks.mailinglist 有多个值

    我刚刚从使用 gitosis 升级到 gitolite 电子邮件通知适用于所有存储库 但对于 gitolite admin 存储库 我在推送时收到此警告 推送很好 git push remote warning hooks announce
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 如何使用 git hook pre-merge-commit 获取原始合并分支名称

    我正在尝试使用新的 git hook pre merge commit 创建一个特定的脚本 但它没有参数 有什么解决方法可以让我获得正在合并的分支的名称吗 例子 在分支 myBranch 上 我调用 git merge testingBra
  • 如何使用 VBA 添加 MS Outlook 提醒事件处理程序

    我想扩展 MS Outlook 以便当弹出日历提醒时 我可以运行一个可以运行外部程序 如批处理脚本 的 VBA 挂钩 就我而言 我想将提醒 转发 到 Linux 桌面 因为我在这两种环境中工作 并且 Windows 桌面并不总是可见 我看到
  • Smartgit:自动插入提交消息

    有没有办法使用钩子脚本在 Smartgit 中自动插入提交消息 重击 如果用户提交了他的更改 我想预加载提交消息字段 我没有看到任何SmartGit配置 http www syntevo com smartgit documentation

随机推荐

  • vSphere ESXI主机网络分析工具

    1 net stats 该命令可以收集端口统计信息 可以通过net stats h 命令显示所有标志 最常见的是使用 net stats l 来确定所有 VMkernel 接口 vmnic 上行链路和 vNIC 端口的交换机端口号和 MAC
  • 算法中的一些数学问题

    1 欧几里得算法 xff08 辗转相除法 xff09 该算法用来快速计算两个整数的最大公约数 递归算法 xff1a int gcd int a int b if b 61 61 0 return a return gcd b a b 非递归
  • 安装pillow已完成,但仍报错No module named ‘PIL‘

    python 3 6 2 xff0c 安装pillow已完成 xff0c 但仍报错No module named 39 PIL 39 no module named 39 pillow 39 python3 6 我加班还不行吗 的博客 CS
  • 使用汇编语言与C语言实现LED1/LED2/LED3三盏灯点亮

    汇编语言代码段 text global start start LED1点灯LED1 gt PE10 64 1 对LED1进行初始化 RCC AHB4 ENSETR MODER OTYPER OSPEEDR PUPDR 64 2 实现LED
  • linux移动文件夹

    使用命令mv 要移动的文件夹 目标文件夹 假如我要将root下的文件amelia txt移动到opt下的文件夹software中 xff0c 我可以使用命令mv root amelia txt opt software amelia txt
  • docker安装nextcloud,聪明人已经收藏了!

    1 为什么要使用分布式锁 使用分布式锁的目的 xff0c 无外乎就是保证同一时间只有一个客户端可以对共享资源进行操作 1 1举一个很长的例子 系统 A 是一个电商系统 xff0c 目前是一台机器部署 xff0c 系统中有一个用户下订单的接口
  • CCF CSP 序列查询新解

    CCF CSP 序列查询新解 C语言 题目背景 上一题 序列查询 中说道 xff1a A 61 A0 A1 A2 An 是一个由 n 43 1 个 0 N 范围内整数组成的序列 xff0c 满足 0 61 A0 lt A1 lt A2 lt
  • 打开edge,出现错误代码: STATUS_ACCESS_DENIED,解决方法

    问题描述 xff1a 这个问题 xff0c 一般显示edge页面加载失败 xff0c 且电脑右下角出现弹窗 解决办法 xff1a 此时 xff0c 你可以到C盘 xff0c 把Microsoft下的子文件删掉 xff0c 注意最好用dele
  • JS的表达式

    一 原始表达式 1 表达式是js的代码形式 2 原始表达式包含直接量 关键字和变量名 xff1b lt script gt 直接量 100 xff1b 200 2 xff1b 34 hi 34 关键字 True False 变量名 a 函数
  • JS的DOM操作——style的操作

    对于JS操作文档中的元素 xff0c 改变其的样式特征需要用到一个属性 style 常见操作 xff1a 获取的元素点 xff08 xff09 style xx 需要设置或修改的属性 代码演示 xff1a 例如修改div块的背景颜色 lt
  • 学会iframe并用其解决跨域问题

    了解iframe 官方定义为 xff1a iframe是HTML标签 xff0c 作用是文档中的文档 xff0c 或者浮动的框架 FRAME iframe元素会创建包含另外一个文档的内联框架 xff08 即行内框架 xff09 简单理解为
  • Vue中的样式绑定

    我们将样式绑定分为两种 xff1a 一种是通过style绑定 xff0c 一种是通过class绑定 样式绑定适用于 切换效果的实现 xff0c 小规模用style xff0c 大规模用class style绑定样式 这里需要用到v bind
  • 51 汇编语言编程:8个按键控制8个LED

    89C51汇编语言写8个按键控制8个LED 按键接P2口 xff0c LED接P1口 有6按键 xff0c 按下对应LED长亮 xff0c 重复按下 xff0c LED灭 xff1b 有两个特殊按键 xff0c 按下 xff0c 对应LED
  • 常见的排序算法

    今天来学习一下数据结构课程中非常重要的排序算法 我们学习一下一些常见的排序算法 xff0c 如冒泡排序 选择排序 快速排序等 1 冒泡排序 实现思路 xff1a 对未排序的各元素从头到尾依次比较相邻的两个元素大小关系 如果左边的队员大 则两
  • Vue的仓库vuex

    Vue js是一个渐进式的框架 xff0c 是一个分层的设计模式 一共分为五层 xff0c 核心库为基础 xff0c 在这基础上添加组件系统 客户端路由 大规模状态管理和开发环境 其中大数据状态管理对应的技术就是vuex xff0c 它是由
  • vue3.0的setup函数以及解决其内的数据不是响应式数据的问题

    相比于2 0 xff0c vue3 0在新增了一个setup函数 xff0c 我们在setup中可以写数据也可以写方法 xff0c 就像我们以前最开始学习js一样 xff0c 在js文件中写代码 如 xff1a setup let name
  • setup中使用watch

    watch属性监听器的作用在vue3 0中没有改变 xff0c 还是监听值得变化 在vue3 0中 xff0c 仍然支持watch配置项 但是我们要在setup中使用watch得话 xff0c 我们要导入watch的API xff0c 然后
  • 缓存相关知识点

    缓存的优点 1 减少不必要的数据传输 xff0c 节省带宽 2 减轻服务器负担 xff0c 提升网站性能 3 加快客户端网页加载速度 4 用户体验更好 缺点 如果资源发生更改 xff0c 客户端不及时更新会导致用户获取信息滞后 缓存类型 分
  • hook之useMemo

    useMemo 这个hook的作用有点像我们以前学习的计算属性一样 xff0c 它会缓存我们上次的结果 xff0c 只有当特定的属性改变时才从新计算 并且他能 记住 任何类型的值 标准写法 useMemo 61 gt return 34 我
  • hook之useContext

    useContext这个hook xff0c 我们通过翻译就可以大致知道它的用途 xff0c 译为使用上下文 context上下文我们在前面就已经使用过了 xff0c 它是一种用于跨组件之间的传值的技术 我们学过Context xff0c