react中,如果父组件要传值给子组件的话,一般可通过props进行传递。但是,当很深层级的组件需要获取外层组件的状态或是公众的数据时,若使用props进行传递的话,则需要一层一层…的往下进行,难免冗余和繁琐,这个时候我们就可以利用Context进行传递。
单个数据 contextType
// 文件1 data.js
import React from 'react';
export const ThemeContext = React.createContext('1');
// 订阅此context的组件 往上层找不到 ThemeContext.Provider 时 默认值 ’1‘ 才生效
// 文件2 App
import React, { Component } from 'react';
import Toolbar from './film3';
import { ThemeContext } from './data'
export default class App extends Component {
state = {
a: 999
}
render() {
return (
<ThemeContext.Provider value={this.state.a}>
<Toolbar />
<span onClick={()=>{
this.setState({
a: this.state.a + 1
})
}}>aa</span>
</ThemeContext.Provider>
);
}
}
// 文件3 film3.js
import React from 'react'
import {ThemeContext} from './data'
export default function Toolbar() {
return (
<div>
<ThemedButton/>
</div>
);
}
class ThemedButton extends React.Component {
static contextType = ThemeContext; // 写法1
render() {
return <div>
{this.context} //999
</div>;
}
}
// ThemedButton.contextType = ThemeContext; 写法1与此写法等价
多个数据时 Consumer
// 文件1 data.js
import React from 'react';
export const ThemeContext = React.createContext('1');
export const LiuContext = React.createContext('liu');
// 文件2 App.js
import React, {Component} from 'react';
import Toolbar from './film3';
import {ThemeContext,LiuContext} from './data';
export default class App extends Component {
state = {
a: 999,
b: 888
}
render() {
return (
<ThemeContext.Provider value={this.state.a}>
<LiuContext.Provider value = {this.state.b}>
<Toolbar />
<span onClick={()=>{
this.setState({
a: this.state.a + 1
})
}}>aa</span>
<span onClick={()=>{
this.setState({
b: this.state.b + 1
})
}}>bb</span>
</LiuContext.Provider>
</ThemeContext.Provider>
);
}
}
// 文件3 film3.js
import React from 'react'
import {ThemeContext,LiuContext} from './data'
export default function Toolbar() {
return (
<div>
<Content />
</div>
);
}
// 一个组件可能会消费多个 context
function Content() {
return (
<ThemeContext.Consumer>
{theme => (
<LiuContext.Consumer>
{user => (
<div>
{user} xx // 888
<br />
{theme} .. // 999
</div>
)}
</LiuContext.Consumer>
)}
</ThemeContext.Consumer>
);
}
------- 手动分割线 -------
请忽略代码中的命名…很早之前就知道context,但因为实际项目中有使用状态管理(redux、mobx),所以一直没怎么了解如何使用,有点太依赖于状态管理了。其实做些小型的项目,完全可以不使用状态管理,这样不但可以更好的帮助自己理解react本身,更可以减小项目的体积。
前端菜鸟,如有问题,还请多多指出~~