首页 > 其他分享 >【React】React18 Hooks 之 useContext

【React】React18 Hooks 之 useContext

时间:2024-07-09 14:29:30浏览次数:10  
标签:const context Hooks React useContext Context 组件 import

目录

在这里插入图片描述

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服务并逐章迭代你的代码,就像参与了真实的项目开发一样。

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

在这里插入图片描述

标签:const,context,Hooks,React,useContext,Context,组件,import
From: https://blog.csdn.net/qq_38951259/article/details/140242950

相关文章

  • 使用react物料
    1.win安装node.js2.安装axios报错,进入到C:\ProgramFiles\nodejs\node_modules\npm目录 成功!安装json-servernpminstalljson-server-g   原文:https://ice.work/docs/guide/about  ......
  • [email protected](52)[email protected](1)- 核心概念
    目录1,MVC2,前端MVC的困难3,Flux4,Redux1,MVC是一个解决方案,用于降低UI和数据关联的复杂度。在早期前后端未做分离时,服务端会响应一个完整的HTML,包含页面需要的所有数据。而浏览器仅承担渲染页面的作用,整体流程也就是服务端渲染。其中服务端的处理流程:处理请求,并将......
  • vue3 watch使用方式,如何监听reactive子属性 ref数据等
    代码<template><divclass="box">childB</div></template><scriptlang="ts"setup>import{reactive,watch,ref}from"vue";constdata1=reactive({msg:"childB",abc:"sl......
  • 两张图带你全面了解React状态管理库:zustand和jotai
    zustand和jotai是当下比较流行的react状态管理库。其都有着轻量、方便使用,和reacthooks能够很好的搭配,并且性能方面,对比React自身提供的context要好得多,因此被很多开发小伙伴所喜爱。更有意思的是,这两个库的作者是同一个人,同时他还开源了另外一个状态库valtio,并没来得及研究......
  • React+TS前台项目实战(二十六)-- 高性能可配置Echarts图表组件封装
    文章目录前言CommonChart组件1.功能分析2.代码+详细注释3.使用到的全局hook代码4.使用方式5.效果展示总结前言Echarts图表在项目中经常用到,然而,重复编写初始化,更新,以及清除实例等动作对于开发人员来说是一种浪费时间和精力。因此,在这篇文章中,将封装一个“高......
  • 前端react入门day06-ReactRouter
    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)目录什么是前端路由创建路由开发环境快速开始抽象路由模块路由导航什么是路由导航声明式导航编程式导航导航传参嵌套路由配置什么是嵌套路由嵌套路由配置默认二级路由404路由配......
  • 空有一身技术却无处施展??找用Python和React写产品的开发同学
    空有一身技术却无处施展??如果您空有一身技术却无处施展,那么机会来了,现在找技术同学一起利用空闲时间和周末时间创造属于自己的产品。目前有两个产品,之前找的外包现在不做了,开发处于停滞状态,因此现在想要找对产品开发真正感兴趣有热情的同学一起做。计划先将这两个产品bug修完,然......
  • react
    也是好久没有更新了,今天更新一下关于react的一些基本操作 什么是reactReact是用于构建用户界面的JavaScript库, [1]起源于Facebook的内部项目,该公司对市场上所有JavaScript MVC框架都不满意,决定自行开发一套,用于架设Instagram的网站。于2013年5月开源产生背景React的......
  • wx.config的前后端实现express和react
    wx.config是微信JS-SDK的配置接口,用于初始化微信JS-SDK。为了确保安全性,微信要求每次调用JS-SDK时都需要进行签名认证。签名认证需要使用jsapi_ticket,而jsapi_ticket需要通过access_token获取。以下是实现wx.config的步骤:后端部分获取AccessToken你需要定期获取并缓存acce......
  • react 2024 07 04
    import{createApi,fetchBaseQuery}from'@reduxjs/toolkit/query/react';import{RootState}from'../store';//定义用户数据的接口interfaceUser{id:number;name:string;sex:string;address?:string;//可选字段job?:string;//可选字段......