任意组件传值-React.createContext的使用
1.React.createContext
的使用场景
- 在开发中,比较常间的数据传递方式是通过
props
属性自上而下(由父到子)进行传递。 - 但是对于有一些场景:比如一些数据需要在多个组件中进行共享(地区偏好、UI主题、用户登录状态、用户信息等)。
- 如果我们在顶层
App
中定义这些信息,之后一层层传递下去,那么对于一些中层不需要数据的组件来说,是一种冗余的操作。 - 我们来看一个例子
import React, { Component } from "react";
function ProfileHeader(props) {//子组件
return (
<div>
<h2>用户昵称:{props.nickName}</h2>
<h2>用户等级:{props.level}</h2>
</div>
);
}
class Profile extends Component {//父组件-包裹子组件
render() {
return (
<div>
<ProfileHeader {...this.props} />
<ul>
<li>内容1</li>
</ul>
</div>
);
}
}
class App extends Component {//祖父组件
constructor(props) {
super(props);
this.state = {
nickName: "张三",
level: 9,
};
}
render() {
return(
<div>
<Profile nickName={this.state.nickName} level={this.state.level} />
<p>我是段落</p>
</div>
);
}
}
export default App;
- 从例子代码可知,从
App
组件中传递了两个属性,经由Profile
组件转发到了ProfileHeader
组件,这个就是一个标准的父子组件嵌套传值的方式,但是也很明显的看出Profile
组件,并没有用到那两个属性,但是数据确确实实经由了Profile
组件。React
提供了一个API
:Context
;Context
提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递props
;Context
设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言;
2.Context相关的API
的使用方法
- 先定义,再供值,再消费
- 定义:
React.createContext
const Context = React.createContext(defaultValue);
- 创建一个需要共享的
Context
对象:返回值是一个组件- 如果一个组件消费了
Context
,那么这个组件会从离自身最近的那个匹配的Context.Provider
中读取到当前的Context
值; defaultValue
是组件在顶层查找过程中没有找到对应的Context.Provider
,那么就使用默认值
- 如果一个组件消费了
- 供应:
Context.Provider
<Context.Provider value={/* 某个值 */}>
- 每个
Context
对象都会返回一个Provider React
组件,它允许消费组件订阅Context
的变化:Context.Provider
接收一个value
属性,传递给消费组件;- 一个
Context.Provider
可以和多个消费组件有对应关系; - 多个
Context.Provider
也可以嵌套使用,里层的会覆盖外层的数据;
- 当
Context.Provider
的value
发生变化的时候,它内部的所有消费组件都会重新渲染;
2.1useContext
-只限于函数组件消费-推荐
- 函数式组件就用
useContext
的方案-简洁明了
import React, { Component, useContext } from "react";
let UserInfo=React.createContext({
nickName:'张三',
level:1
})
let Theme=React.createContext('红色')
function ProfileHeader() {//函数式组件就用useContext的方案-简洁明了
let userInfo=useContext(UserInfo)
console.log(userInfo);//{nickName: '张三', level: 1}
let theme=useContext(Theme)
console.log(theme);//中国红
return (
<div>
<h2>主题颜色:{theme}</h2>
<h2>用户昵称:{userInfo.nickName}</h2>
<h2>用户等级:{userInfo.level}</h2>
</div>
);
}
class Profile extends Component {//父组件-包裹子组件
render() {
return (
<div>
<ProfileHeader/>
<ul>
<li>内容1</li>
</ul>
</div>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
nickName: "张三",
level: 9,
};
}
render() {
return(
<div>
{/* 注意点:如果包裹了组件,value必须存在值,它不会去读默认值的 */}
<UserInfo.Provider value={{nickName:'李四',level:9}} >
<Theme.Provider value="中国红">
<Profile/>
</Theme.Provider>
</UserInfo.Provider>
<p>我是段落</p>
</div>
);
}
}
export default App;
2.2Context.Consumer
函数式组件/类式组件-不推荐
2.2.1函数式组件
import React, { Component, useContext } from "react";
import { Fragment } from "react/cjs/react.production.min";
let UserInfo=React.createContext({
nickName:'张三',
level:1
})
let Theme=React.createContext('红色')
function ProfileHeader() {
return (
<div>
<UserInfo.Consumer>
{
userInfo=>{
console.log(userInfo);//{nickName: '李四', level: 9}
return <Theme.Consumer>
{
theme=>{
console.log(theme);//中国红
return (
<Fragment>
<h2>主题颜色:{theme}</h2>
<h2>用户昵称:{userInfo.nickName}</h2>
<h2>用户等级:{userInfo.level}</h2>
</Fragment>
)
}
}
</Theme.Consumer>
}
}
</UserInfo.Consumer>
</div>
);
}
class Profile extends Component {
render() {
return (
<div>
<ProfileHeader/>
<ul>
<li>内容1</li>
</ul>
</div>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
nickName: "张三",
level: 9,
};
}
render() {
return(
<div>
{/* 注意点:如果包裹了组件,value必须存在值,它不会去读默认值的 */}
<UserInfo.Provider value={{nickName:'李四',level:9}} >
<Theme.Provider value="中国红">
<Profile/>
</Theme.Provider>
</UserInfo.Provider>
<p>我是段落</p>
</div>
);
}
}
export default App;
2.2.2类式组件
import React, { Component, useContext,Fragment } from "react";
let UserInfo = React.createContext({
nickName: "张三",
level: 1,
});
let Theme = React.createContext("红色");
class ProfileHeader extends Component{
render() {
return (
<div>
<UserInfo.Consumer>
{(userInfo) => {
console.log(userInfo); //{nickName: '李四', level: 9}
return (
<Theme.Consumer>
{(theme) => {
console.log(theme); //中国红
return (
<Fragment>
<h2>主题颜色:{theme}</h2>
<h2>用户昵称:{userInfo.nickName}</h2>
<h2>用户等级:{userInfo.level}</h2>
</Fragment>
);
}}
</Theme.Consumer>
);
}}
</UserInfo.Consumer>
</div>
);
}
}
class Profile extends Component {
render() {
return (
<div>
<ProfileHeader />
<ul>
<li>内容1</li>
</ul>
</div>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
nickName: "张三",
level: 9,
};
}
render() {
return (
<div>
{/* 注意点:如果包裹了组件,value必须存在值,它不会去读默认值的 */}
<UserInfo.Provider value={{ nickName: "李四", level: 9 }}>
<Theme.Provider value="中国红">
<Profile />
</Theme.Provider>
</UserInfo.Provider>
<p>我是段落</p>
</div>
);
}
}
export default App;
2.3Class.contextType
值只限于类组件-不推荐
- 挂载在
class
上的静态属性contextType
会被重赋值为一个由React.createContext()
创建的Context
对象: - 这能让你使用
this.context
来消费最近Context
上的那个值; - 你可以在任何生命周期中访问到它,包括
render
函数中; - 缺点:只能接一个
React.createContext
组件的value
import React, { Component, useContext,Fragment } from "react";
let UserInfo = React.createContext({
nickName: "张三",
level: 1,
});
let Theme = React.createContext("红色");
class ProfileHeader extends Component {
render() {
console.log(this.context);//{nickName: '李四', level: 9}
return (
<div>
<h2>用户昵称:{this.context.nickName}</h2>
<h2>用户等级:{this.context.level}</h2>
</div>
);
}
// 缺点就是只能接一个React.createContext组件的value
static contextType = UserInfo;
}
class Profile extends Component {
render() {
return (
<div>
<ProfileHeader />
<ul>
<li>内容1</li>
</ul>
</div>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
nickName: "张三",
level: 9,
};
}
render() {
return (
<div>
<UserInfo.Provider value={{ nickName: "李四", level: 9 }}>
<Theme.Provider value="中国红">
<Profile />
</Theme.Provider>
</UserInfo.Provider>
<p>我是段落</p>
</div>
);
}
}
export default App;
2.4什么时候使用默认值defaultValue
呢?
<UserContext.Provider value={{ nickname: "why", level: 99 }}></UserContext.Provider>
<Profile />
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhibfbbi
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22 -
excel打印预览压线压字怎么办
PHP中文网 06-22