React Context 理解和使用

更新日期: 2021-02-26阅读: 1.7k标签: React

基本概念

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.Consumer API 可以让我们即使是在函数式组件也可以订阅到 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 中


链接: https://fly63.com/article/detial/10169

如何优雅的设计 React 组件

如今的 Web 前端已被 React、Vue 和 Angular 三分天下,尽管现在的 jQuery 已不再那么流行,但 jQuery 的设计思想还是非常值得致敬和学习的,特别是 jQuery 的插件化。

React深度编程:受控组件与非受控组件

受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意。这恰恰显示React的威力,满足不同规模大小的工程需求。

React框架学习_关于React两种构建应用方式选择

一般在传统模式下,我们构建前端项目很简单。就是下载各种js文件,如JQuery、Echart等,直接放置在html静态文件。Webpack则是JavaScript中比较知名的打包工具。这两个构建工具构成了React应用快速搭建的基础。

Gatsby.js_一款基于React.js静态站点生成工具

Gatsby能快速的使用 React 生态系统来生成静态网站,可以结合React Component、Markdown 和服务端渲染来完成静态网站生成让他更强大。

React创建组件的三种方式及其区别

React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归;具体的三种方式:函数式定义的无状态组件、es5原生方式React.createClass定义的组件、es6形式的extends React.Component定义的组件

react生命周期详解_深入理解React生命周期

React主要思想是通过构建可复用组件来构建用户界面,每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段改变和执行。所谓组件就是有限状态机,,表示有限个状态以及在这些状态之间的转移和动作行为的模型。

React + Webpack 构建打包优化

React 相关的优化:使用 babel-react-optimize 对 React 代码进行优化,检查没有使用的库,去除 import 引用,按需打包所用的类库,比如 lodash 、echarts 等.Webpack 构建打包存在的问题两个方面:构建速度慢,打包后的文件体积过大

react router中页面传值的三种方法

这篇文章主要介绍React Router定义路由之后如何传值,有关React和React Router 。react router中页面传值的三种方法:props.params、query、state

react 高阶组件的 理解和应用

react 高阶组件简单的理解是:一个包装了另一个基础组件的组件。高阶组件的两种形式:属性代理(Props Proxy)、反向继承 (Inheritance Inversion)

react中的refs属性的使用方法

React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!