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 的相关文章

  • 为什么 Windows 挂钩收不到某些消息?

    Microsoft 不建议将 DirectInput 用于键盘和鼠标输入 因此 我编写了一个输入管理器类 它使用 SetWindowsHookEx 来挂钩 WndProc 和 GetMsg 我相信钩子设置得当 尽管它们看起来是各种问题的原因
  • 张量流中使用的钩子是什么意思

    我无法理解python tensorflow中Hook的确切含义 LearningRateSetterHook tf train SessionRun Hook 如果您向我解释一下 我将不胜感激 谢谢 这可能是一个关于什么是钩子的更普遍的问
  • C++ 挂钩 winsock

    我正在尝试挂接winsock send 和recv 以读取进程的所有流量 我将以下代码作为 dll 注入目标进程中 include dll h include
  • 低级鼠标和键盘钩子回调在哪个线程中运行?

    我正在设置一个低级鼠标钩与SetWindowsHookEx HANDLE handle SetWindowsHookEx WH MOUSE LL callback GetModuleHandle NULL NULL 因为这是一个低级回调 所
  • 如何劫持 Caps Lock 键以进行剪切、复制、粘贴键盘操作

    这是我想要实现的目标 To Copy press and release Caps Lock ONCE To Paste press and release Caps Lock TWICE quickly To Cut press Ctrl
  • 禁用单个 git 命令的钩子

    鉴于我需要在我的钩子脚本中使用 git 我希望我的钩子脚本本身不触发钩子 所以我想在每个命令的基础上跳过钩子 即我正在寻找如下选项 git no hooks some git command 您可以使用 git c core hooksPa
  • 监控应用程序对 DLL 的调用

    简而言之 我想监视从应用程序到 DLL 的选定调用 我们有一个旧的 VB6 应用程序 我们丢失了它的源代码 当时公司没有使用源代码控制 此应用程序使用第 3 方 DLL 我想在新的 C 应用程序中使用这个 DLL 不幸的是 DLL API
  • IOS越狱如何拦截短信/短信

    我目前正在尝试编写一个应用程序来拦截文本消息并根据该消息的内容做出反应 我试图挂钩 receivedMessage struct CKSMSRecord message replace BOOL replaceCKSMSService 类中
  • PInvoke 调用外部 SetWindowsHookEx 和 GetModuleHandle 时出错

    我正在尝试将程序中的 Windows 挂钩设置为外部 EXE 这将用于监视窗口的大小调整 最小化 因此我可以类似地调整程序大小 停靠到窗口 如何解决错误代码1428 and 126 below 打电话时设置WindowsHookEx使用 n
  • 如何在 WordPress 中设置动态 `home` 和 `siteurl`?

    我使用动态配置多语言设置locale筛选 其中获取子域名来确定语言 function load custom language locale get the locale code according to the sub domain n
  • WPF 中的全局鼠标挂钩

    我需要获取鼠标在屏幕上的位置NOT在我的应用程序中 我用过全局鼠标和键盘钩子here http www codeproject com Articles 7294 Processing Global Mouse and Keyboard H
  • Git CHMOD 接收后挂钩

    我在网络服务器上使用一个裸露的远程存储库 并带有一个接收后挂钩 该挂钩会自动将我的文件推送到 public html 目录中 问题是 我使用的是 codeigniter index php 文件必须是 chmod 755 我使用 filez
  • 如何为钩子创建蹦床函数

    我对挂钩很感兴趣 我决定看看是否可以挂钩一些函数 我对使用 detours 这样的库不感兴趣 因为我想拥有自己做的经验 通过我在互联网上找到的一些资源 我能够创建下面的代码 这是基本的 但效果还不错 然而 当挂钩由多个线程调用的函数时 它被
  • PyInstaller 2.1导入自定义包

    我有一个脚本正在尝试使用 Python 2 7 使用 PyInstaller 2 1 进行编译 该脚本使用我编写的名为 auto common 的自定义包 在脚本中 我使用以下命令导入它 sys path append path to pa
  • 从 C# 连接到 Windows 文件复制 API

    有没有办法从 C 连接到 Windows 文件复制 API 我知道这需要非托管代码 但代码示例或入门程序会很有帮助 我已经看过 C 代码 但都是希腊语 UPDATE 我很抱歉 我应该更清楚地表达我的意图 我实际上希望将 Windows 的复
  • 调用 GetPointerFrameTouchInfo 时出现错误 998(对内存位置的访问无效)[重复]

    这个问题在这里已经有答案了 我正在尝试致电GetPointerFrameTouchInfo函数来获取指针计数 但该函数似乎失败了 错误 998 对内存位置的访问无效 知道为什么会发生这种情况以及如何解决它吗 我试图在钩子过程中调用相同的方法
  • 挂钩 Win32 窗口创建/调整大小/查询大小

    我正在尝试 扩展 现有的应用程序 The goal就是在不更改应用程序代码的情况下使现有应用程序变得更大 一个约束拉伸的应用程序不会 注意到 它 因此 如果应用程序查询创建的窗口大小 它将看到原始大小 而不是调整后的大小 我设法使用调整窗口
  • 在 Mac OS X 中获取进程创建通知

    我正在尝试为 Mac OS X 编写 kext 当任何进程启动时都会收到通知 在 Windows 中 您可以通过调用 PsSetLoadImageNotifyRoutine 并指定在进程启动时调用的回调来完成此操作 这是有记录的方式 它适用
  • Flutter Redux 和 Hook。如何像react一样观察useEffect内部变量实例的变化?

    我是 flutter 新手 试图观察像 React Native 这样处于减速器状态的变量 count 我使我的 redux 和 hook 工作完美 屏幕上的变量计数发生变化 但如果我更改操作 则永远不会再次调用 useEffect 仅一次
  • 键盘挂钩获取组合键(WPF)

    我尝试在这里使用这篇文章 在 WPF C 中使用全局键盘钩子 WH KEYBOARD LL https stackoverflow com questions 1639331 using global keyboard hook wh ke

随机推荐

  • 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