【React】React18 Hooks 之 useContext

目录

  • useContext
    • 1、Provider和 useContext
    • 2、Provider 和Consumer
    • 3、Provider 嵌套
    • 4、React.createContext提供的Provider和class的contextType属性
    • 5、读、写Context
      • (1)父组件修改Context
      • (2)子组件修改Context
  • 好书推荐

在这里插入图片描述

useContext官方地址
使用 Context 深度传递数据

通常,您会通过 props 将信息从父组件传递到子组件。但是,如果您必须通过中间的许多组件传递信息,或者应用中的许多组件都需要相同的信息,则传递 props 会变得冗长且不方便。Context允许父组件向其下方树中的任何组件(无论深度如何)提供一些信息,而无需通过 props 明确传递

简单来说使用Context可以实现跨组件层级传递数据,不用层层传递数据。本文介绍三种Context的使用方式。

  • 函数组件:React.createContext提供的ProvideruseContext钩子
  • React.createContext提供的ProviderConsumer
  • Provider嵌套
  • Class组件:React.createContext提供的ProviderclasscontextType属性
  • 读、写Context

useContext

useContext是一个 React Hook,可让您从组件读取和订阅上下文。

用法:

const value = useContext(SomeContext)

参数的含义:
SomeContext:使用createContext创建的上下文。上下文本身并不包含信息,它只代表您可以提供或从组件中读取的信息类型。
返回值的含义:
value:useContext返回调用组件的上下文值,传递给最接近的SomeContext的值

1、Provider和 useContext

新建个context.js,导出createContext()的返回值

import { createContext } from "react";
export default createContext();

App.js,导入上面写的context,并使用context提供的Provider组件进行包裹,圈定局部的全局作用域,传值后可以提供给子组件进行消费。当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。

import Context from "./context";
import Test from "./Test"
function App() {const value = "app 中的数据"return (<><Context.Provider value={value}><div className="Appy" ><Test /></div></Context.Provider></>);
}export default App;

新建个Test.js,

import Context from "./context"
import MyComponent from "./MyComponent"
const Test1 = () => {return <><MyComponent/><div></div></>
}
export default Test1

新建个MyComponent.js,使用useContext钩子接收Context提供的参数

import Context from "./context"
import { useContext } from "react"
const MyComponent = ()=>{const value = useContext(Context)return <><div>value:{value}</div></>
}
export default MyComponent

可以看到页面中显示如下:
在这里插入图片描述
使用Components分析如下:

在这里插入图片描述

2、Provider 和Consumer

上面的MyComponent.js 文件,我们可以使用Context.Consumer组件接收数据。在MyComponent组件中,导入context,使用其提供的Consumer组件来订阅Context的变更,需要一个函数作为子元素,函数的第一个形参便是Provider组件提供的value值。如下:

import Context from "./context"
import { useContext } from "react"
const MyComponent = ()=>{const value = useContext(Context)return <><Context.Consumer>{value=><div>value1:{value}</div>}</Context.Consumer></>
}
export default MyComponent

3、Provider 嵌套

新建context.js,创建ThemeContext,AuthContext,然后再分别创建创建 ThemeContext 、AuthContext 的 Provider 组件,Provider 组件主要提供方法。


// context.js
import React, { createContext, useState, useContext } from 'react';// 创建 ThemeContext
const ThemeContext = createContext();// 创建 ThemeContext 的 Provider 组件
const ThemeProvider = ({ children }) => {const [theme, setTheme] = useState('light'); // 假设初始主题是 'light'// 可以通过函数来切换主题const toggleTheme = () => {setTheme(theme === 'light' ? 'dark' : 'light');};return (<ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>);
};// 创建 AuthContext
const AuthContext = createContext();// 创建 AuthContext 的 Provider 组件
const AuthProvider = ({ children }) => {const [user, setUser] = useState(null); // 假设初始用户是 null// 可以通过函数来设置用户const login = (userData) => {setUser(userData);};const logout = () => {setUser(null);};return (<AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>);
};// 导出 ThemeProvider 和 AuthProvider,以及它们各自的 Context
export { ThemeContext, ThemeProvider, AuthContext, AuthProvider };

App.js,导入ThemeProvider, AuthProvider,层层嵌套。

import React from 'react';
import { ThemeProvider, AuthProvider } from './context.js'; // 导入提供者
import MyComponent from './MyComponent'; // 假设您有一个 MyComponent 组件const App = () => {return (<ThemeProvider ><AuthProvider ><MyComponent /> {/* MyComponent 现在可以访问 ThemeContext 和 AuthContext */}</AuthProvider></ThemeProvider>);
};export default App;

MyComponent.js,导入ThemeContext, AuthContext ,使用useContext获取ThemeContext, AuthContext 的Provider组件传递的参数。

import React, { useContext } from 'react';
import { ThemeContext, AuthContext } from './context.js'; // 导入 Contextconst MyComponent = () => {console.log(useContext(ThemeContext),'useContext(ThemeContext)')const { theme, toggleTheme } = useContext(ThemeContext);const { user, login, logout } = useContext(AuthContext);console.log(useContext(AuthContext),'useContext(ThemeContext)')// 使用 theme、toggleTheme、user、login 和 logout 做一些事情...return (// ... 组件的 JSX<div><p>当前主题: {theme}</p><button onClick={toggleTheme}>切换主题</button>{user ? (<div><p>已登录用户: {user.name}</p><button onClick={logout}>登出</button></div>) : (<button onClick={() => login({ name: 'John Doe' })}>登录</button>)}</div>);
};export default MyComponent;

页面如下:
在这里插入图片描述

4、React.createContext提供的Provider和class的contextType属性

static contextType 是一种在类组件中直接访问 Context 值的方式,而不必明确地传递一个 <Context.Consumer> 组件。static contextType 应该被定义在类组件的外部,而不是在 render 方法内部或组件的类体内部。

挂载在 class 上的 contextType 属性会被重赋值为一个由React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。
使用static关键字添加静态属性,和直接在class添加属性效果一致,最终都会添加到类上,而不是类的实例上

import React, { Component } from "react";
import context from "./context";
class Test1 extends Component {static contextType = context;render() {console.log(Test1.contextType,'contextType');console.log(this.context,'context');const value = this.context;return <div>第三种使用Context方式获取的值:{JSON.stringify(value)}</div>;}
}// Test1.contextType = context; //此处与写static关键字作用一致
export default Test1;

可以看到打印的Test1.contextTypeReact.createContext() 创建的 Context 对象,打印this.context为最近的 Context 上的值
在这里插入图片描述

5、读、写Context

(1)父组件修改Context

App.js中,更改Context数据,调用组件中的onChange方法。Provider的value不再传入一个简单结构的对象,而是将useState的返回值作为新对象的key/value,子组件便能调用App的setStore函数进行更新

import Context from "./context";
import Test from "./Test1" 
import { useState } from "react"
function App() {const value = "app 中的数据"const [store, setStore] = useState(value);const onChange = ()=>{setStore("app 数据 change")}return (<><Context.Provider value={{store, setStore}}><div className="Appy" ><Test /><button onClick={onChange}>按钮</button></div></Context.Provider></>);
}export default App;

Test.js中,使用useContext接收Context数据。点击父组件中的按钮,数据从 app 中的数据变为app 数据 change

import Context from "./context"
import { useContext } from "react"
const Test1 = () => {const value = useContext(Context)console.log(value,'test1组件接收到的')return <>{value.store}<div></div></>
}
export default Test1

(2)子组件修改Context

这里更改子组件的代码,新增一个button按钮,使用context接收过来的setStore函数,修改Context数据。点击button之后,数据由app 中的数据变为子组件修改Context成功。效果与在父组件中修改Context数据一样。

import Context from "./context"
import { useContext } from "react"
// import MyComponent from "./MyComponent"
const Test1 = () => {const context = useContext(Context)return <>{value.store}<button onClick={()=>context.setStore("子组件修改Context成功")}>子组件button</button></>
}
export default Test1

好书推荐

《Rust Web开发》

如果你厌倦了缓慢、占用大量资源且不稳定的模板化Web开发工具,Rust就是你的解决方案。Rust服务提供了稳定的安全保证、非凡的开发经验,以及能够自动防止常见错误的编译器。

《Rust Web开发》教你使用Rust以及重要的Rust库(如异步运行时的Tokio、用于Web服务器和API的Warp,以及运行外部HTTP请求的Reqwest)来创建服务端的Web应用。《Rust Web开发》包含大量的代码示例以及专业的提示,以帮助你创建项目和组织代码。随着学习的深入,你将创建一个完整的Q&A Web服务并逐章迭代你的代码,就像参与了真实的项目开发一样。

这不是一本参考书,而是一本工作手册。正在构建的应用程序在设计上做出了一些妥协,以便在适当的时候解释概念。需要阅读整本书的内容才能最终将应用程序部署到生产环境中。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/372705.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring框架Mvc(2)

1.传递数组 代码示例 结果 2.集合参数存储并进行存储类似集合类 代码示例 postman进行测试 &#xff0c;测试结果 3.用Json来对其进行数据的传递 &#xff08;1&#xff09;Json是一个经常使用的用来表示对象的字符串 &#xff08;2&#xff09;Json字符串在字符串和对象…

XLSX + LuckySheet + LuckyExcel + Web Worker实现前端的excel预览

文章目录 功能简介简单代码实现web worker 版本效果参考 功能简介 通过LuckyExcel的transformExcelToLucky方法&#xff0c; 我们可以把一个文件直接转成LuckySheet需要的json字符串&#xff0c; 之后我们就可以用LuckySheet预览excelLuckyExcel只能解析xlsx格式的excel文件&a…

九、Linux二进制安装ElasticSearch集群

目录 九、Linux二进制安装ElasticSearch集群1 下载2 安装前准备(单机&#xff0c;集群每台机器都需要配置)3 ElasticSearch单机&#xff08;7.16.2&#xff09;4 ElasticSearch集群&#xff08;8.14.2&#xff09;4.1 解压文件&#xff08;先将下载文件放到/opt下&#xff09;4…

生物素标记降钙素Biotin-α-CGRP, rat 中间体

生物素标记降钙素Biotin-α-CGRP, rat 中间体是一种特定的生物化学试剂&#xff0c;主要用于科学研究领域。以下是对该产品的详细介绍&#xff1a; 一、基本信息 产品名称&#xff1a;生物素标记降钙素Biotin-α-CGRP, rat 中间体 英文名称&#xff1a;Biotin-α-CGRP, rat 纯度…

AI转绘_animatediff-cli-prompt-travel

这个工具有两种主要模式&#xff1a;它可以直接通过提示创建视频&#xff0c;或者它可以对现有视频进行风格化。还有方法可以提高视频的分辨率。 正如工具名称所示&#xff0c;它的一个主要特点是"提示旅行"。这意味着你可以例如使用特定的提示用于前20帧&#xff0…

koa + http-proxy-middleware 搭建一个带转发的静态服务器

背景 由于工作中碰到写普通页面&#xff08;未使用脚手架&#xff09;&#xff0c;需要发起接口请求&#xff0c;但普通页面又无法对接口发起正常请求&#xff0c;故编写一个Koa搭建的带转发功能的静态服务器。 起步 新建一个文件夹&#xff0c;在文件夹下打开 cmd 或者 git …

手写简单实现IOC

这个小demo是利用反射从最基础一步一步模拟实现了IOC的功能,所有的代码基本都给出了注释,方便大家阅读. 目录结构&#xff1a; 这里需要导入一下junit依赖 <!-- junit测试 --><dependency><groupId>junit</groupId><artifactId>junit</artif…

解决vite 断点调试定位不准确问题

问题&#xff1a;vite构建时&#xff0c;控制台报错行数等信息定位不准确或debugger断点调试定位不准确 解决&#xff1a;F12后打开设置面板&#xff0c;把“JavaScript源代码映射”去掉可临时解决&#xff0c;如需永久解决需升级vite到最新版 还有一种&#xff1a; 参考&…

Unity--射线检测--RayCast

Unity–射线检测–RayCast 1.射线检测的含义 射线检测,根据名称而言,使用一条射线来检测是击中了某个物体/多个物体 射线检测的包含两个部分: 射线和检测 2.射线检测可以用在哪些地方 射击游戏&#xff1a; 玩家的瞄准和射击&#xff1a;检测玩家视线是否与敌人或其他目标…

JRE、JVM、JDK分别是什么。

JDK JDK的英文全称是Java Development Kit。JDK是用于制作程序和Java应用程序的软件开发环境。JDK 是 Java 开发工具包&#xff0c;它是 Java 开发者用来编写、编译、调试和运行 Java 程序的集合。JDK 包括了 Java 编译器&#xff08;javac&#xff09;、Java 运行时环境&…

首席数据官CDO证书报考指南:方式、流程、适考人群与考试难度

在信息泛滥的今天&#xff0c;数据已转变为企业不可或缺的宝贵资源。 面对海量的信息&#xff0c;如何提炼出价值&#xff0c;为企业带来实质性的收益&#xff1f;首席数据官&#xff08;CDO&#xff09;认证的出现正是为了满足这一需求&#xff0c;它不仅是个人专业能力的体现…

【网络安全】这些网络安全知识请牢记!

随着社会信息化深入发展&#xff0c;互联网对人类文明进步将发挥更大促进作用&#xff0c;但与此同时&#xff0c;互联网领域的问题也日益凸显&#xff0c;网络犯罪、网络攻击等时有发生&#xff0c;网络安全与每个人都息息相关&#xff0c;下面一起来了解网络安全知识吧&#…

如何降低电力运维成本,为企业的运维增效、能源数字化和节能降耗提供数据支持?

【电力运维存在问题】 随着全球范围内城镇化、数字化和工业化进程的加速与电力政策的改革&#xff0c;企业用电需求不断攀升&#xff0c;极大冲击了电力企业传统的运维模式&#xff0c;暴露出许多的问题&#xff1a; 变电所较为分散&#xff0c;缺乏统一管理&#xff1b;站内…

从数据仓库到数据湖(下):热门的数据湖开源框架

文章目录 一、前言二、Delta Lake三、Apache Hudi四、Apache Iceberg五、Apache Paimon六、对比七、笔者观点八、总结八、参考资料 一、前言 在上一篇从数据仓库到数据湖(上)&#xff1a;数据湖导论文章中&#xff0c;我们简单讲述了数据湖的起源、使用原因及其本质。本篇文章…

Linux:Ubuntu18.04下开机自启动QT图形化界面

Linux&#xff1a;Ubuntu18.04下开机自启动QT图形化界面 Chapter1 Linux&#xff1a;Ubuntu18.04下开机自启动QT图形化界面一、创建rc.local文件二、建立rc-local.service文件三、启动服务查看启动状态四、重启 Chapter2 将QT应用作为开机自启动&#xff08;Linux系统&#xff…

Simulink生成代码时端口名称乱码问题

写在最前&#xff1a; 在使用Simulink生成代码时发现端口名称与模型中定义的输如输出端口名称不一致&#xff0c;代码生成的端口名称为随机字符名称。 在生成的H文件中发现&#xff0c;端口定义的结构体名称与模型中实际定义的名称不符。 模型中的定义 检查后发现&#xff0c…

【已解决】腾讯云安装了redis,但是本地访问不到,连接不上

汇总了我踩过的所有问题。 查看配置文件redis.conf 1、把bind 127.0.0.1给注释掉&#xff08;前面加个#就是&#xff09;或者改成bind 0.0.0.0&#xff0c;因为刚下载时它是默认只让本地访问。&#xff08;linux查找文档里的内容可以输入/后面加需要匹配的内容&#xff0c;然后…

基于STM主题模型的主题提取分析-完整代码数据

直接看结果: 代码: import re from collections import defaultdict import random import matplotlib.pyplot as plt import numpy as npimport pandas as pd import numpy as np import re from sklearn.feature_extraction.text import CountVectorizer from nltk.corpus…

如何在 Ubuntu上搭建 LAMP

远程登录 Ubuntu系统环境 ssh (User)(IP) # 比如&#xff1a;ssh lennlouis192.168.207.128 为安全起见&#xff0c;建议你使用 root 登录 VPS 后创建一个具有 sudo 权限的帐号。 安装和配置 Apache 2 Apache Http Server 是一个开源的&#xff0c;非常流行&#xff0c;使用…

【Dell R730 折腾记录】风扇调速--在 Ubuntu 系统上开机自启动并每隔30分钟执行一次风扇定速脚本

前段时间升级了一下机柜里的服务器&#xff0c;替换掉了一台旧的 Dell 服务器&#xff0c;换上了这台 R730。但是无奈于噪音的袭扰&#xff0c;搁置了一段时间。我在这台机器上目前安装了一块 Intel Xeon E5-2630v3 芯片以及一张改过散热的 NVIDIA Tesla P4 计算卡。结果就是散…