目录
useContext官方地址
使用 Context 深度传递数据
通常,您会通过 props 将信息从父组件传递到子组件。但是,如果您必须通过中间的许多组件传递信息,或者应用中的许多组件都需要相同的信息,则传递 props 会变得冗长且不方便。Context允许父组件向其下方树中的任何组件(无论深度如何)提供一些信息,而无需通过 props 明确传递。
简单来说使用
Context
可以实现跨组件层级传递数据,不用层层传递数据。本文介绍三种
Context
的使用方式。
- 函数组件:
React.createContext
提供的Provider
和useContext
钩子 React.createContext
提供的Provider
和Consumer
- Provider嵌套
- Class组件:
React.createContext
提供的Provider
和class
的contextType
属性 - 读、写
Context
useContext
useContext是一个 React Hook,可让您从组件读取和订阅上下文。
用法:
const value =useContext(SomeContext)
参数的含义:
SomeContext:使用createContext创建的上下文。上下文本身并不包含信息,它只代表您可以提供或从组件中读取的信息类型。
返回值的含义:
value:useContext返回调用组件的上下文值,传递给最接近的SomeContext的值。
1、Provider和 useContext
新建个context.js,导出createContext()的返回值
import{ createContext }from"react";exportdefaultcreateContext();
App.js,导入上面写的context,并使用context提供的Provider组件进行包裹,圈定局部的全局作用域,传值后可以提供给子组件进行消费。当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。
import Context from"./context";import Test from"./Test"functionApp(){const value ="app 中的数据"return(<><Context.Provider value={value}><div className="Appy"><Test /></div></Context.Provider></>);}exportdefault App;
新建个Test.js,
import Context from"./context"import MyComponent from"./MyComponent"constTest1=()=>{return<><MyComponent/><div></div></>}exportdefault Test1
新建个MyComponent.js,使用useContext钩子接收Context提供的参数
import Context from"./context"import{ useContext }from"react"constMyComponent=()=>{const value =useContext(Context)return<><div>value:{value}</div></>}exportdefault MyComponent
可以看到页面中显示如下:
使用Components分析如下:
2、Provider 和Consumer
上面的
MyComponent.js
文件,我们可以使用Context.Consumer组件接收数据。在MyComponent组件中,导入context,使用其提供的Consumer组件来订阅Context的变更,需要一个函数作为子元素,函数的第一个形参便是Provider组件提供的value值。如下:
import Context from"./context"import{ useContext }from"react"constMyComponent=()=>{const value =useContext(Context)return<><Context.Consumer>{value=><div>value1:{value}</div>}</Context.Consumer></>}exportdefault MyComponent
3、Provider 嵌套
新建context.js,创建ThemeContext,AuthContext,然后再分别创建创建 ThemeContext 、AuthContext 的 Provider 组件,Provider 组件主要提供方法。
// context.jsimport React,{ createContext, useState, useContext }from'react';// 创建 ThemeContextconst ThemeContext =createContext();// 创建 ThemeContext 的 Provider 组件constThemeProvider=({ children })=>{const[theme, setTheme]=useState('light');// 假设初始主题是 'light'// 可以通过函数来切换主题consttoggleTheme=()=>{setTheme(theme ==='light'?'dark':'light');};return(<ThemeContext.Provider value={{ theme, toggleTheme }}>{children}</ThemeContext.Provider>);};// 创建 AuthContextconst AuthContext =createContext();// 创建 AuthContext 的 Provider 组件constAuthProvider=({ children })=>{const[user, setUser]=useState(null);// 假设初始用户是 null// 可以通过函数来设置用户constlogin=(userData)=>{setUser(userData);};constlogout=()=>{setUser(null);};return(<AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>);};// 导出 ThemeProvider 和 AuthProvider,以及它们各自的 Contextexport{ ThemeContext, ThemeProvider, AuthContext, AuthProvider };
App.js,导入ThemeProvider, AuthProvider,层层嵌套。
import React from'react';import{ ThemeProvider, AuthProvider }from'./context.js';// 导入提供者import MyComponent from'./MyComponent';// 假设您有一个 MyComponent 组件constApp=()=>{return(<ThemeProvider ><AuthProvider ><MyComponent />{/* MyComponent 现在可以访问 ThemeContext 和 AuthContext */}</AuthProvider></ThemeProvider>);};exportdefault App;
MyComponent.js,导入ThemeContext, AuthContext ,使用useContext获取ThemeContext, AuthContext 的Provider组件传递的参数。
import React,{ useContext }from'react';import{ ThemeContext, AuthContext }from'./context.js';// 导入 ContextconstMyComponent=()=>{
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>);};exportdefault 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";classTest1extendsComponent{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关键字作用一致exportdefault Test1;
可以看到打印的
Test1.contextType
为
React.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"functionApp(){const value ="app 中的数据"const[store, setStore]=useState(value);constonChange=()=>{setStore("app 数据 change")}return(<><Context.Provider value={{store, setStore}}><div className="Appy"><Test /><button onClick={onChange}>按钮</button></div></Context.Provider></>);}exportdefault App;
Test.js中,使用
useContext
接收
Context
数据。点击父组件中的按钮,数据从
app 中的数据
变为
app 数据 change
import Context from"./context"import{ useContext }from"react"constTest1=()=>{const value =useContext(Context)
console.log(value,'test1组件接收到的')return<>{value.store}<div></div></>}exportdefault Test1
(2)子组件修改Context
这里更改子组件的代码,新增一个button按钮,使用context接收过来的setStore函数,修改Context数据。点击button之后,数据由
app 中的数据
变为
子组件修改Context成功
。效果与在父组件中修改Context数据一样。
import Context from"./context"import{ useContext }from"react"// import MyComponent from "./MyComponent"constTest1=()=>{const context =useContext(Context)return<>{value.store}<button onClick={()=>context.setStore("子组件修改Context成功")}>子组件button</button></>}exportdefault Test1
好书推荐
《Rust Web开发》
如果你厌倦了缓慢、占用大量资源且不稳定的模板化Web开发工具,Rust就是你的解决方案。Rust服务提供了稳定的安全保证、非凡的开发经验,以及能够自动防止常见错误的编译器。
《Rust Web开发》教你使用Rust以及重要的Rust库(如异步运行时的Tokio、用于Web服务器和API的Warp,以及运行外部HTTP请求的Reqwest)来创建服务端的Web应用。《Rust Web开发》包含大量的代码示例以及专业的提示,以帮助你创建项目和组织代码。随着学习的深入,你将创建一个完整的Q&A Web服务并逐章迭代你的代码,就像参与了真实的项目开发一样。
这不是一本参考书,而是一本工作手册。正在构建的应用程序在设计上做出了一些妥协,以便在适当的时候解释概念。需要阅读整本书的内容才能最终将应用程序部署到生产环境中。
版权归原作者 不叫猫先生 所有, 如有侵权,请联系我们删除。