Context概念
一般用在跨组件通信中。
如上面的组件树中,A组件与B组件之间隔着非常多的组件,假如A组件希望传递给B组件一个属性,那么不得不使用props将属性从A组件历经一系列中间组件传递给B组件。
这样代码不仅非常的麻烦,更重要的是中间的组件可能压根就用不上这个属性,却要承担一个传递的职责,这是我们不希望看见的。
Context出现的目的就是为了解决这种场景,使得我们可以直接将属性从A组件传递给B组件。
旧Context(不推荐使用)
过时的API官方文档传送门
基本用法
假定,ABC三个组件,AC为祖孙关系,AB父子关系,现在使用context
由A向C传递属性text
。
class A extends React.Component {
getChildContext() {
return { text: 'Hello孙子' }
}
render() {
return (
<div>组件A包含<B/></div>
)
}
}
A.childContextTypes = { text: PropTypes.string };
class B extends React.Component {
render() {
return (
<div>组件B包含<C/></div>
)
}
}
class C extends React.Component {
render() {
const { text } = this.context;
return (
<div>我是C我接收到A传递的内容是{text}</div>
)
}
}
C.contextTypes = { text: PropTypes.string }
留意上述代码中用以提供context
的API
,只要给上层组件添加getChildContext
和childContextTypes
,React
将自动向下传递信息,子树上的所有组件可以通过定义 contextTypes
来访问 context
。
带来的问题
假如我们想要更新context
,那么只能通过更新state
或者props
并将其值赋值给context
。
class A extends React.Component {
constructor(props) {
super(props);
this.state = { text: 'Hello孙子' };
}
getChildContext() {
return { text: this.state }
}
updateState = () => {
this.state = { text: '我是你爷爷' };
}
render() {
return (
<div onClick={this.updateState} >组件A包含<B /></div>
)
}
}
A.childContextTypes = { text: PropTypes.string };
但是,如果A组件提供的一个context
发生了变化,而中间父组件(B)的 shouldComponentUpdate
返回 false
,那么实际上B和C都不会进行更新。使用了context
的组件则完全失控,所以基本上没有办法能够可靠的更新context
。
新Context
官方文档传送门
还是上述例子,AC祖孙组件通信。使用createContext
可以构建一个Provider
用以给孙子组件传递props
。
const defaultVal = { text: 'Hello,孙子' };
const AContext = React.createContext(defaultVal);
class App extends React.Component {
constructor(props) {
...,
this.state = { text: '这里是新的内容' }
}
render() {
return (
<AContext.Provider value={this.state}>
<B />
</AContext.Provider>
)
}
}
// 接收方式1-定义contextType
import { AContext } from './A';
class C extends React.Component {
static contextType = AContext;
render() {
const { text } = this.context;
return (
<div>我是C我接收到A传递的内容是{text}</div>
)
}
}
// 接收方式2-使用consumer
// consumer主要用以函数组件渲染
import { AContext } from './A';
class C extends React.Component {
render() {
return (
<AContext.Consumer>
({ text }) => (
<p>我是C我接收到A传递的内容是{text}</p>
)
</AContext.Consumer>
)
}
}
Redux中的Context
// 待续补坑
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。