前文有讲到Vue中的provide透传,祖孙组件之间通信。在react中也有类似的存在,他就是context,context的作用也是让祖孙组件之前通信。
React中,通过createContext方法来创建一个Context对象。
import React, { createContext } from 'react';
const context = createContext();
createContext
方法可以传入参数,该参数会当作默认值传入。
createContext
创建的context
暴露出一个Provider组件,该组件value的属性值会透传到每一个子组件里。暴露出的Consumer
组件用于函数式组件获取传递过来的值,下面会介绍使用。
const { Provider, Consumer } = context;
export default class ContextDom extends Component {
state = {
name: 'dz',
age: 18
}
render() {
return (
<div className="ctx pad">
父级组件A 我的名字是:{this.state.name}
<Provider value={{...this.state}}>
<B />
</Provider>
</div>
)
}
}
下级组件
类组件
通过将Class的contextType属性指定给上面createContext
创建的context
class C extends Component {
static contextType = context
render() {
return (
<div className="pad grand">
从A组件继承过来的名字是:{this.context.name}
<D />
</div>
)
}
}
或者
class C extends Component {
render() {
return (
<div className="pad grand">
从A组件继承过来的名字是:{this.context.name}
<D />
</div>
)
}
}
C.contextType = context
现在可以通过this.context
访问传递的值,不论你在哪个生命周期,都能访问到!
函数式组件
通过上面暴露出的Consumer组件或者react提供的hooks来接收值
export default function D() {
return (
<div className="pad last">
<Consumers>
{
value => `从A组件接收的值 名字是:${value.name}`
}
</Consumers>
</div>
)
}
或者
import React, { useContext } from 'react';
export default function C() {
const { name, age } = useContext(context);
return (
<div className="pad grand">
从A组件继承过来的名字是:{name}
从A组件继承过来的年龄是:{age}
<D />
</div>
)
}
官网文档貌似有说
如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。
相当于把所有的值放到一个props里,然后每个组件都要接收props。个人感觉还是太繁琐了,换汤不换药啊,只能说是比不聚合在一起要简洁一点吧。
Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。
所以官方的建议是尽量少用 (谨慎使用)这个api,不然会让你的组件复用性降低。
over
贴一下当初学习时写的demo吧 Github仓库