React Context 理解和使用
写在前面
鉴于笔者学习此内容章节 React官方文档 时感到阅读理解抽象困难,所以决定根据文档理解写一篇自己对Context的理解,文章附带示例,以为更易于理解学习。更多内容请参考 React官方文档
如果您觉得文章对您有帮助,可以点击文章右下角【[推荐](javascript:void(0)】一下。您的鼓励是笔者创作的最大动力!
如果发现文章有问题也可以在文章下方及时联系笔者哦,相互探讨一起进步~
基本概念
Context是React中为了避免在不同层级组件中逐层传递props的产物,在没有Context的时候父组件向子组件传递props属性只能在组件树上自上而下进行传递,但是有些属性并不是组件树的每层节点都有相同的需求,这样我们再这样逐层传递props就显得代码很繁琐笨重。- 使用
React.createContext(defulData)可以通过创建一个ContextObject,在某个组件中调用ContextObject.Provider同时可以设置新的value = newData覆盖掉defulData共享到下面的所有子组件,需要ContextObject共享出来的数据的子组件可以通过static contextType = ContextObject接收到data,使用this.context即可调用data
适用场景
- 很多不同层级的组件需要访问同样的数据,所以如果我们只是想避免层层传递一些属性,那么我们还有更好的选择: 组合组件
Context API 理解与运用
- React.createContext(defaultValue)
创建一个Context对象,defaultValue是默认参数,在一个组件中可以调用这个对象的ProviderAPI,并且设置新的参数:
const Context = React.createContext(defaultValue)
function ContextProvider () {
return (
<Context.Provider value = { newValue }>
/* 子组件(这里的组件及其子组件都可以收到这个Context对象发出的newValue) */
<Context.Provider/>
)
}
但是如果没有对应的Context.Provider相匹配,那么组件树上的所有组件都可以收到这个Context对象发出 的defaultValue;
同时可以调用Context的ConsumerAPI可以用来接受到Context的值,并且根据这个值渲染组件:
function ContextConsumer () {
return (
<Context.Comsumer>
{value =>
<div>
/* 可以根据value进行渲染 */
</div>
}
</Context.Comsumer>
)
}
Context.Provider & Context.Comsumer
<MyContext.Provider value={ variableValue }>可以允许消费组件订阅到variableValue值的变化,也就是说消费组件可以根据variableValue值的变化而变化,variableValue的值我们可以定义一个事件来控制改变;
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
利用
Context.ConsumerAPI 可以让我们即使是在函数式组件也可以订阅到 Context的值;这种方法需要一个函数作为子元素,函数接收当前的context值,并返回一个 React 节点。
传递给函数的
value值等价于组件树上方离这个 context 最近的 Provider 提供的variableValue值。如果没有对应的 Provider,value参数等同于传递给createContext()的defaultValue。// Provider 结合 Consumer 使用示例
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 创建 Context 对象
const MyContext = React.createContext(0) // defaultValue 是数字0 // App组件 渲染 Context 对象
class App extends React.Component {
constructor(props){
super(props);
this.state = {
variableValue : 0
}
// 处理 Provider中value变化的函数
this.handleChange = () => {
this.setState(state => ({
variableValue: state.variableValue + 1
})
)
}
}
render(){
return (
// 调用 Context.Provider, 设置可以让Consumer组件监听变化的 value 值
<MyContext.Provider value = {this.state.variableValue}>
<Context changeValue = {this.handleChange}/>
</MyContext.Provider>
)
}
}
// 消费组件
class Context extends React.Component{
render(){
return (
<MyContext.Consumer>
/* 根据Context的value进行渲染 */
{value =>
<button onClick={this.props.changeValue} >
Add MyValue:{value}
</button>
}
</MyContext.Consumer>
)
}
}
ReactDOM.render(
<App className = 'app'/>
,
document.getElementById('root')
);
当Provider的
variableValue值发生变化时,它内部的所有消费组件都会重新渲染。Class.contextType
class MyClass extends React.Component {
render() {
let value = this.context; // this.context 可以访问到 MyClass 的contextType
/* 基于 MyContext 组件的值进行渲染 */
}
}
MyClass.contextType = MyContext; //将MyClass的contextType属性赋值为 Context 对象的值
挂载在 class 上的
contextType属性会被重赋值为一个由React.createContext()创建的 Context 对象。此属性能让你使用this.context来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。注: 从文档的字面意思,
Class.contextType是类组件特有的API,所以函数式组件只能使用Context.Consumer来访问Context对象的值,我们可以来试一下类组件和函数式组件的API:import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 创建 Context 对象
const MyContext = React.createContext(0)
// App组件 渲染 Context 对象
class App extends React.Component {
constructor(props){
super(props);
this.state = {
variableValue : 0
}
this.handleChange = () => {
this.setState(state => ({
variableValue: state.variableValue + 1
})
)
}
}
render(){
return (
// 调用 Context.Provider, 设置可以让Consumer组件监听变化的 value 值
<MyContext.Provider value = {this.state.variableValue}>
<Context_consumer changeValue = {this.handleChange} />
<br/>
<Context_contextType changeValue = {this.handleChange} />
<br />
<Func_Consumer changeValue = {this.handleChange} />
<br />
<func_contextType changeValue = {this.handleChange} />
</MyContext.Provider>
)
}
}
// Class & Consumer 消费组件
class Context_consumer extends React.Component{
render(){
return (
<MyContext.Consumer>
{value =>
<button onClick={this.props.changeValue} >
Add Class_consumer:{value}
</button>
}
</MyContext.Consumer>
)
}
}
// Class & contextType 的消费组件
class Context_contextType extends React.Component{
render(){
let value = this.context
return (
<button onClick={this.props.changeValue} >
Add Class_contextType:{value}
</button>
)
}
};
Context_contextType.contextType = MyContext;
// 函数组件 & Consumer
function Func_Consumer (props) {
return (
<MyContext.Consumer>
{value =>
<button onClick={props.changeValue} >
Add Func_consumer:{value}
</button>
}
</MyContext.Consumer>
)
} // 函数组件 & contextType
function func_contextType (props) {
let value = this.context
return (
<button onClick={props.changeValue} >
Add func_contextType:{value}
</button>
)
}
func_contextType.contextType = MyContext; ReactDOM.render(
<App className = 'app'/>
,
document.getElementById('root')
);运行结果:
除了func_contextType组件之外其他组件都可以正常运行
Context.displayName
context 对象接受一个名为
displayName的 property,类型为字符串。React DevTools 使用该字符串来确定 context 要显示的内容。示例,下述组件在 DevTools 中将显示为 MyDisplayName:
const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
<MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中
React Context 理解和使用的更多相关文章
- 探索 Redux4.0 版本迭代 论基础谈展望(对比 React context)
Redux 在几天前(2018.04.18)发布了新版本,6 commits 被合入 master.从诞生起,到如今 4.0 版本,Redux 保持了使用层面的平滑过渡.同时前不久, React 也从 ...
- context理解
官方文档的解释是:Context提供了关于应用环境全局信息的接口.它是一个抽象类,它的执行被Android系统所提供.它允许获取以应用为特征的资源和类型.同时启动应用级的操作,如启动Activity, ...
- React context基本用法
React的context就是一个全局变量,可以从根组件跨级别在React的组件中传递.React context的API有两个版本,React16.x之前的是老版本的context,之后的是新版本的 ...
- [React] Prevent Unnecessary Rerenders of Compound Components using React Context
Due to the way that React Context Providers work, our current implementation re-renders all our comp ...
- React Context API
使用React 开发程序的时候,组件中的数据共享是通过数据提升,变成父组件中的属性,然后再把属性向下传递给子组件来实现的.但当程序越来越复杂,需要共享的数据也越来越多,最后可能就把共享数据直接提升到最 ...
- React Hooks +React Context vs Redux
React Hooks +React Context vs Redux https://blog.logrocket.com/use-hooks-and-context-not-react-and-r ...
- 对 React Context 的理解以及应用
在React的官方文档中,Context被归类为高级部分(Advanced),属于React的高级API,但官方并不建议在稳定版的App中使用Context. 很多优秀的React组件都通过Conte ...
- [译]React Context
欢迎各位指导与讨论 : ) 前言 由于笔者英语和技术水平有限,有不足的地方恳请各位指出.我会及时修正的 O(∩_∩)O 当前React版本 15.0.1 时间 2016/4/25 正文 React一个 ...
- 对React的理解
转自:http://www.cocoachina.com/webapp/20150721/12692.html 现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了R ...
随机推荐
- dedecms万能SQL标签使用方法大全
注意:dede_archives这是系统默认的数据库表,如果你修改过表前缀dede_,请自行更改表名.在以下示例的标签中,有一部分只写出了SQL语句,具体的完整标签写法请参考:织梦SQL标签调用方法. ...
- Vue.js到前端工程化
b站视频地址:黑马程序员Vue.js到前端工程化(webpack打包,以及Vue-cli3和Element-UI的使用) vue学习系列 1.vue概述 2.vue基本使用 3.vue模板语法 4.指 ...
- 一周精彩内容分享(第 1 期):"世纪逼空大战"
这里记录过去一周,我看到的值得分享的东西. 一方面是整理记录一下自己一周的学习,另一方面也是期待自己有更多的输出,有更多的价值. 周刊开源(Github:wmyskxz/weekly),欢迎提交 is ...
- 2019牛客暑期多校训练营(第八场)A.All-one Matrices(dp)
题意:又是最大01矩阵的模型了 这次要找的是极大0/1矩阵的个数 思路:我们像处理最大01矩阵那样处理一下边界 由于我们上左右已经无法再继续扩展 我们只需要用前缀和记录一下是否可以向下扩展(即判断当前 ...
- 2019-2020 ACM-ICPC Brazil Subregional Programming Contest (11/13)
\(2019-2020\ ACM-ICPC\ Brazil\ Subregional\ Programming\ Contest\) \(A.Artwork\) 并查集,把检测区域能在一起的检测器放在 ...
- 【bzoj 4455】小星星(树型DP+容斥原理+dfs建树和计算的2种方式)
题意:给一个n个点的图和一个n个点的树,求图和树上的点一一对应的方案数.(N<=17) 解法:1.在树的结构上进行tree DP,f[i][j]表示树上点 i 对应图上点 j 时,这个点所在子树 ...
- Atcoder ABC155_C中有关c++ STL map的用法
题目:https://atcoder.jp/contests/abc155/tasks/abc155_c 这道题的题意是给我们n个string,让我们统计每个string出现的次数,并输出次数最多的一 ...
- woj1010 alternate sum 数学 woj1011 Finding Teamates 数学
title: woj1010 alternate sum 数学 date: 2020-03-10 categories: acm tags: [acm,woj,数学] 一道数学题.简单. 题意 给一个 ...
- 深入理解JavaScript垃圾回收
JavaScript中的垃圾回收是自动进行的,在平常开发中我们可能并不在意,但是深入理解JavaScript中的垃圾回收却是必要的; JavaScript 中主要的内存管理概念是 可达性,简而言之就是 ...
- 前端 Web 异常监控系统 All In One
前端 Web 异常监控系统 All In One Sentry https://sentry.io trackjs https://trackjs.com/ rollbar https://rollb ...