Context
用法
不想在组件树中通过逐层传递Props的方式来传递数据。可以使用Context来实现跨层级的组件数据传递。
context提供了一个无需为每层组件手动添加props,就能在组件树之间进行数据传递的方法。
Context提供了一种在组件之间共享此类值的方式,而不需要显示地通过组件树的逐层传递props。
何时使用
Context设计目的是为了共享那些对于一个组件树而言是 全局 的数据。例如当前认证的用户,主题或者首选语言。
// demo: 通过一个theme属性改变按钮的样式
// 组件嵌套 App=>ToolBar => ThemeButton
// 不使用context
class App extends Component{
render(){
return(
<ToolBar theme = "dark" />
)
}
}
function ToolBar(props){
return (
<div>
<ThemeButton theme ={ props.theme} />
</div>
)
}
class ThemeButton extends React.Component{
render(){
return <Button theme={ this.props.theme}/>
}
}
如何使用
如果要Context发挥作用,需要用到两种组件,一个是Context生产者,通常是一个父节点。另一个是Context的消费组件。通常是一个或者多个子节点。所以Context的使用基于生产者消费者模式。
使用context,可以避免中间元素传递props
使用步骤:
- 引入context 使用React.createContext(value) 方法,参数为要共享的属性的属性值,属性名可以自定义保存
const ThemeContext = React.createContext('light')
- 使用Provider将当前的theme传递给以下的组件树。(需要共享某个属性的组件的最外层)
<ThemeContext.Provider value = "dark"> 要共享状态的组件 </ThemeContext.Provider>
属性value 为要默认值
- 使用值
在组件树中,要使用共享属性的组件才需要做处理, 不使用的组件不做处理。
在需要的组件内,定义静态变量 接收context
static contextType = ThemeContext
共享属性就是需要使用组件上的一个属性,属性值要设置为我们需要用到的属性
属性值 可以通过 this.context 获取
// Context 可以让我们无需明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的theme创建一个context(light 为默认值)
const ThemeContext = React.createContext('light')
class App extends React.Component{
render(){
return (
<ThemeContext.Provider value ="dark" >
<Toolbar />
</ThemeContext.Provider>
)
}
}
// 中间的组件也无需指明往下传递theme
function Toolbar(props){
return (
<div>
<ThemeButton>
</div>
)
}
class ThemeButton extends React.Component{
// 指定contextType读取当前的 theme context
// React会往上找到当前的theme Provider 然后使用它的值
static contextType = ThemeContext
render(){
return <Button theme ={ this.context }>
}
}
API
React.createContext
语法
const MyContext = React.createContext(defaultValue)
使用
创建一个Context对象,当React渲染了一个订阅了这个Context对象的组件,这个组件会从组件的树中里自身最近的那个匹配的Provider中读取到当前的context值。
只有当组件所在的树中没有匹配到Provider时,其defaultValue才会生效。这有助于在不适用Provider包装组件的情况下对组件进行测试。
注意
将undefined传给Provider的value时,defaultValue不会生效。
Context.Provider
语法
<MyContext.Provider value = "{ /* 某个值 */}">
每个Context对象都会返回一个Provider React组件。,允许消费者组件订阅context的变化
Provider接收一个value属性,传递给子组件,这个消费者组件为生产者组件的后代组件。
一个生产者组件可以连接多个消费者组件。
生产者组件可以被嵌套以覆盖数中更深层次的值。
每当生产者组件的value属性变化时,所有作为生产者后代的消费者组件都将重新渲染,并且不受shouldComponentUpdate的约束。
Class.contextType
可以为类上的contextType属性分配由React.createContext()创建的Context对象。
分配之后,允许使用this.context 在消费者组件中使用该Context类型的最近的当前值。
可以在任何生命周期方法中引用它,包含render函数
class MyClass extends React.Component {
componentDidMount() {
let value = this.context;
/* perform a side-effect at mount using the value of MyContext */
}
componentDidUpdate() {
let value = this.context;
/* ... */
}
componentWillUnmount() {
let value = this.context;
/* ... */
}
render() {
let value = this.context;
/* render something based on the value of MyContext */
}
}
MyClass.contextType = MyContext;
总结
如何使用Context
- 生产者组件中 创建Context对象 使用React.createContext( defaultValue)
- 生产者中 使用 Context.Provider 包裹 消费者组件 ,让消费者组件订阅这个Context对象
- 消费者 中 使用类属性 Class.contextType 接收创建好的Context对象 Class.contextType = MyContext
- 消费者组件中使用 this.context 来接收该Context类型的最近的当前值