从上级而下一层一层的传递
function Toolbar(props){
console.log('props',props);
return (
<div>
<ThemeButton theme={props.theme}/>
</div>
)
}
function Button(props){
return <div>
{props.theme}
</div>
}
class ThemeButton extends Component{
render(){
console.log('this.props.theme',this.props.theme);
return <Button theme={this.props.theme}>Button</Button>
}
}
使用Context
const ThemeContext = React.createContext('light');
function Toolbar(){
return(
<ThemeButton/>
)
}
function Text(props){
return <h2>
{ props.theme}
</h2>
}
class ThemeButton extends Component{
static contextType = ThemeContext;
render(){
return(
<Text theme={this.context}/>
)
}
}
class Contexts extends Component{
render(){
return(
<ThemeContext.Provider value="dark">
<Toolbar/>
</ThemeContext.Provider>
)
}
}
const ThemeContext = React.createContext('light');
<ThemeContext.Provider value='dark'>
</ThemeContext.Provider>
static contextType = ThemeContext;
API
React.createContext
const MyContext = React.createContext(defaultValue);
创建一个Context对象对。当React渲染订阅这个context对象的组件时,它将从组件树中匹配最接近的Provider中读取当前的context。
defaultValue参数仅当consumer(使用者)在树中没有匹配的Provider(提供者)时使用它,这有利于在不封装它们的情况下对组件进行测试。
注意:
将undefined作为Provider(提供者)值传递不会导致consumer(使用者)组件使用defaultValue。
Context.Provider
<MyContext.Provider value={/*some value*/}/>
每个Context对象都附带一个Provider React组件,允许consumer(使用者)组件来订阅context的改变。
Class.contextType
可以为类上的contextType属性分配由React.createContext()创建的context对象。这允许您使用this.context使用Context类型的最近的当前值。您可以在任何生命周期中引用它,包括render函数。
Context.Consumer
<Context.Consumer>
</Context.Consumer>
一个可以订阅context变化的React组件。这允许您订阅函数式组件中的context。
示例
动态Context
/**
* Created by mapbar_front on 2019/8/1.
*/
import React,{Component} from 'react';
// import {ThemeContext,themes} from './../../utils/utils';
const themes = {
light: {
background: '#f99',
},
dark: {
background: '#9ff',
}
}
const ThemeContext = React.createContext(themes.light);
function Toolbar(props){
return (
<ThemeButton onClick={props.changeTheme}>
ThemeButton
</ThemeButton>
)
}
class ThemeButton extends Component{
constructor(props){
super(props);
}
render(){
let props = this.props;
console.log('props',props);
let theme = this.context;
return(
<button {...props} style={{background: theme.background}}>
btn
</button>
)
}
}
ThemeButton.contextType = ThemeContext;
class Context1 extends Component{
constructor(props){
super(props);
this.state = {
theme: themes.light,
}
}
toggleTheme=()=>{
console.log('toggleTheme');
this.setState(state=>({
theme: state.theme === themes.dark ? themes.light: themes.dark
}))
}
render(){
return(
<div>
<ThemeContext.Provider value={this.state.theme}>
<Toolbar changeTheme={this.toggleTheme}/>
</ThemeContext.Provider>
<div>
<ThemeButton/>
</div>
</div>
)
}
}
export default Context1;
从嵌套组件更新Context
/**
* Created by mapbar_front on 2019/8/1.
*/
import React,{Component} from 'react';
const themes = {
light: {
background: '#f99',
},
dark: {
background: '#9ff',
}
}
const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: ()=>{}
})
function Content(){
return(
<div>
<ThemeToggleButton/>
</div>
)
}
function ThemeToggleButton(){
return(
<ThemeContext.Consumer>
{
({theme,toggleTheme})=>(
<button
onClick={ toggleTheme }
style={{ backgroundColor:theme.background }}
>
btn
</button>
)
}
</ThemeContext.Consumer>
)
}
class Context2 extends Component{
constructor(props){
super(props);
this.state = {
theme: themes.light,
toggleTheme: this.toggleTheme,
}
}
toggleTheme=()=>{
this.setState(state=>({
theme: state.theme === themes.dark?themes.light:themes.dark
}))
}
render(){
return(
<div>
<ThemeContext.Provider value={this.state}>
<Content />
</ThemeContext.Provider>
</div>
)
}
}
export default Context2;
使用多个context
/**
* Created by mapbar_front on 2019/8/1.
*/
import React,{Component} from 'react';
const ThemeContext = React.createContext('light');
const UserContext = React.createContext({
name:'xiao',
});
function SlideBar(){
return(
<h2>
SlideBar
</h2>
)
}
function Layout(){
return(
<div>
<SlideBar/>
<Content/>
</div>
)
}
function ProfilePage(props){
console.log('ProfilePage',props);
return(
<div>
<p>{props.user}</p>
<p>{props.theme}</p>
</div>
)
}
function Content(){
return(
<ThemeContext.Consumer>
{
theme=>(
<UserContext.Consumer>
{
user=>(
<ProfilePage user={user} theme={theme}/>
)
}
</UserContext.Consumer>
)
}
</ThemeContext.Consumer>
)
}
class Context3 extends Component{
render(){
const {signedInUser,theme} = this.props;
return(
<div>
<ThemeContext.Provider value='theme'>
<UserContext.Provider value='signedInUser'>
<Layout/>
</UserContext.Provider>
</ThemeContext.Provider>
</div>
)
}
}
export default Context3;