【React】React18 Hooks 之 useContext

news2024/9/24 5:22:26

目录

  • 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'; // 导入 Context

const 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.coloradmin.cn/o/1910501.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

72小时快速入门大语言模型

&#x1f393; 随着人工智能技术的飞速发展&#xff0c;国产芯片在大语言模型领域的应用成为创新的前沿阵地。硬蛋学堂携手行业精英&#xff0c;隆重推出全新课程——"基于国产芯片的大语言模型技术开发及应用"&#xff0c;开启智能科技的新篇章&#xff01; &#…

电阻负载柜的主要特性和参数是什么?

电阻负载柜作为重要的电力测试仪器&#xff0c;其主要特性和参数对于理解其功能和应用至关重要。以下是对电阻负载柜主要特性和参数的详细阐述&#xff1a; 主要特性 高精度测量&#xff1a;电阻负载柜通常配备高精度的电压、电流和功率因数测量系统&#xff0c;能够准确反映被…

如何创建录取查询系统

随着新学期的脚步渐近&#xff0c;老师们的日程表上又添上了密密麻麻的任务。开学前的准备工作总是让人应接不暇&#xff0c;从整理教材到布置教室&#xff0c;再到准备课程计划&#xff0c;每一项工作都需要细心与耐心。而在这些繁琐的事务中&#xff0c;如何高效地将录取结果…

哪些独立站外链策略最有效?

在当前的SEO领域中&#xff0c;独立站外链策略的效果差异很大&#xff0c;但GPB外链无疑是其中最为有效的一种。GPB外链&#xff0c;指的是通过高质量、包收录且dofollow的顶级域名独立站来获得外链&#xff0c;这种外链策略能够显著提升目标网站的整体排名数据。 关键词排名的…

Java面试八股之MySQL的redo log和undo log

MySQL的redo log和undo log 在MySQL的InnoDB存储引擎中&#xff0c;redo log和undo log是两种重要的日志&#xff0c;它们各自服务于不同的目的&#xff0c;对数据库的事务处理和恢复机制至关重要。 Redo Log&#xff08;重做日志&#xff09; 功能 redo log的主要作用是确…

[matlab]周期性信号分析

目录 信号预处理 周期性特征提取方法 频谱分析 傅里叶变换 快速傅里叶变换&#xff08;FFT&#xff09; 周期图法 Welch法 自相关分析 时频分析 基于模型的方法 时间序列分解 应用实例 提取信号的周期性特征是一个在信号处理领域广泛应用的技术&#xff0c;特别是在…

业务咨询方案 + IT落地方案建议设计

近期&#xff0c;在深入探索咨询方案的实施与落地路径时&#xff0c;体会到了一系列心得与启示&#xff0c;旨在为未来的项目实践提供可借鉴的蓝本。 咨询方案的精髓&#xff0c;在于“业务引领&#xff0c;IT支撑”的核心理念。所以方案的前提是在于业务的梳理&#xff1b; …

java Web学习笔记(一)

1. 前置学习知识 JavaScript学习笔记 CSS3学习笔记 html学习笔记 2. Tomcat介绍 前端App的运行环境&#xff1a; 服务器 --> JRE --> Tomcat --> App Tomcat目录文件介绍 bin:该目录下存放的是二进制可执行文件&#xff0c;如果是安装版&#xff0c;那么这个目…

Java-链表中倒数最后k个结点

题目&#xff1a; 输入一个长度为 n 的链表&#xff0c;设链表中的元素的值为 ai &#xff0c;返回该链表中倒数第k个节点。 如果该链表长度小于k&#xff0c;请返回一个长度为 0 的链表。 数据范围&#xff1a;0≤&#x1d45b;≤1050≤n≤105&#xff0c;0≤&#x1d44e;…

【Qt5】入门Qt开发教程,一篇文章就够了(详解含qt源码)

目录 一、Qt概述 1.1 什么是Qt 1.2 Qt的发展史 1.3 Qt的优势 1.4 Qt版本 1.5 成功案例 二、创建Qt项目 2.1 使用向导创建 2.2 一个最简单的Qt应用程序 2.2.1 main函数中 2.2.2 类头文件 2.3 .pro文件 2.4 命名规范 2.5 QtCreator常用快捷键 三、Qt按钮小程序 …

69岁的Java之父-------宣布退休了?

文章目录 高斯林的编程之路Java的诞生与Oracle的分道扬镳从Google到AWS退休生活 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;该系列文章专栏&#x…

基于泰坦尼克号生还数据进行 Spark 分析

基于泰坦尼克号生还数据进行 Spark 分析 在这篇博客中&#xff0c;我们将展示如何使用 Apache Spark 分析著名的泰坦尼克号数据集。通过这篇教程&#xff0c;您将学习如何处理数据、分析乘客的生还情况&#xff0c;并生成有价值的统计信息。 数据解析 • PassengerId &#…

C语言笔记30 •单链表经典算法OJ题-2.移除链表元素•

移除链表元素 1.问题 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 2.代码实现&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h&g…

私人订制:模块化沙箱

沙箱技术&#xff0c;作为一种在计算机安全领域广泛应用的技术手段&#xff0c;其核心目的是为应用程序或进程提供一个隔离的运行环境&#xff0c;以限制其对系统资源的访问和潜在的安全风险。随着技术的不断发展&#xff0c;沙箱技术逐渐实现了模块化&#xff0c;这种模块化的…

反向代理概念

反向代理概念 代理&#xff1a; 简单来说&#xff0c;找一个中间人代替我去做一件事情&#xff0c;只要他给我结果就可以。 正向代理: 隐藏客户端的身份&#xff0c;通过代理获取结果 案例1&#xff1a; 1、入职了中国j建设银行&#xff0c;做开发 2、自己电脑不能上网&#x…

2024年全国青少年信息素养大赛复赛及决赛、我知道的有这些

周末两天2024年全国青少年信息素养大赛复赛部分赛区已经结束&#xff0c;还没有考试的同学加紧备考后面的2次&#xff0c;成绩预计&#xff08;7月13日、7月20日两次考试&#xff09;结束之后的2周左右出&#xff0c;2024年全国青少年信息素养大赛决赛将在2024年8月16日-20日在…

程序设计方法论总结

程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用&#xff0c;简单才好维护。因此&#xff0c;不应该以评论艺术品的眼光来评价程序设计是否优秀&#xff0c;程序设计的艺术不在于有多复杂多深沉&#xff0c;…

Vue89-Vuex中多组件共享数据

一、需求 1-1、count组件读取persons数据 借助mapState映射。 1-2、personList组件读取sum数据

聚观早报 | 蚁天鉴2.0发布;理想汽车推送无图NOA

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 7月8日消息 蚁天鉴2.0发布 理想汽车推送无图NOA 特斯拉推送FSD v12.4.3 iQOO Neo9s Pro配色公布 百川智能AI健康…

python--实验7 函数(1)

知识点 函数的定义与调用 函数分类&#xff1a;内置函数和自定义函数。函数定义&#xff1a;使用def关键字定义函数&#xff0c;包括函数名、参数列表和函数体。注意&#xff1a; &#xff08;1&#xff09;即使该函数不需要接收任何参数&#xff0c;也必须保留一对空的圆括号…