盒子
盒子
文章目录󰁋
  1. 简介
  2. 例1
  3. 例2
  4. context在Provider种应用

React之context

简介

  • React 组件之间的通信是基于 props 的单向数据流,即父组件通过 props 向子组件传值,亦或是子组件执行传入的函数来更新父组件的state,这都满足了我们大部分的使用场景
  • 一般地,对于兄弟组件之间的通信,是通过它们共同的祖先组件进行的,即 Lifting State Up,官方文档也有介绍。组件一通过事件将状态变更通知它们共同的祖先组件,祖先组再将状态同步到组件二
  • 但是,如果组件之间嵌套的比较深,即使提升状态到共同父组件,再同步状态到相应的组件还是需要一层一层的传递下去,可能会比较繁琐
  • 在对应的场景中,context 就可以缩短父组件到子组件的属性传递路径

例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import Parent from './Parent'
import ChildOne from '../components/ChildOne'
import ChildTwo from '../components/ChildTwo'

export default class Container extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' }
}

changeValue = value => {
this.setState({ value })
}

getChildContext() {
return {
value: this.state.value,
changeValue: this.changeValue
}
}

render() {
return (
<div>
<Parent>
<ChildOne />
</Parent>
<Parent>
<ChildTwo />
</Parent>
</div>
)
}
}

Container.childContextTypes = {
value: PropTypes.string,
changeValue: PropTypes.func
}

Parent.jsx

1
2
3
4
5
6
7
import React from "react"

const Parent = (props) => (
<div {...props} />
)

export default Parent

ChildOne.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export default class ChildOne extends React.Component {

handleChange = (e) => {
const { changeValue } = this.context
changeValue(e.target.value)
}

render() {
return (
<div>
子组件一
<input onChange={this.handleChange} />
</div>
)
}
}

ChildOne.contextTypes = {
changeValue: PropTypes.func
}

ChildTwo.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default class ChildTwo extends React.Component {
render() {
return (
<div>
子组件二
<p>{this.context.value}</p>
</div>
)
}
}

ChildTwo.contextTypes = {
value: PropTypes.string
}

Container.childContextTypes 中进行接口的声明,通过 getChildContext 返回更新后的state,在 Child.contextTypes 中声明要获取的接口,这样在子组件内部就能通过 this.context 获取到。通过 Context 这样一个中间对象,ChildOneChildTwo 就可以相互通信了

例2

组件嵌套传递属性,在导航里面引用Page中的变量

  • 使用context来传递
  • 使用props层级传递

使用context组件需要定义propTypes,需要严格校验、声明类型、字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Page extends React.Component {
static childContextTypes = {
user:PropTypes.string
}
constructor(props){
super(props)
this.state = {user:'poetries'}
}
getChildContext(){
return this.state
}
render(){
return (
<div>
<p>我是{this.state.user}</p>
<Siderbar />
</div>
)
}
}

class Siderbar extends React.Component {
static childContextTypes = {
user:PropTypes.string
}
render(){
return (
<div>
<p>侧边栏</p>
<Navbar />
</div>
)
}
}
class Navbar extends React.Component {
static childContextTypes = {
user:PropTypes.string
}
render(){
return (
<div>
<p>我是{this.context.user}的导航栏</p>
<Siderbar />
</div>
)
}
}

context在Provider种应用

provider组件就是使用context,把store放到context里,所有的子元素可以直接取到store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import PropTypes from 'prop-types'
class Provider extends Component {
static childContextTypes = {
store:Protypes.object
}
constructor(props,context){
super(props,context)
this.store = props.store
}
getChildContext(){
//把传进来的store放进全局
return {store:this.store}
}
render(){
return this.props.children
}
}

connect 负责连接组件,给到redux里的数据放到组件的属性里

  • 负责接收一个组件,把state里的一些数据放进去,返回一个组件
  • 数据变化的时候,能够通知组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//高阶组件写法
const connect = (mapStateToProps=state=>state,mapDispatchToProps={})=>(wrapperComponent)=>{
return class ConnectComponent extends React.Component {
//负责接收组件
static contextTypes = {
store:PropTypes.obejct
}
constructor(props){
super(props, context){
this.state = {
props:{}
}
}
}
componentDidMount(){
const {store} = this.context
store.subscribe(()=>this.update())
this.update()
}
update(){
// 获取mapStateToProps、mapDispatchToProps 放入this.props里

const {store}=this.context
const stateProps = mapStateToProps(store.getState())
const dispatchProps = bindActionCreators(mapDispatchProps,store.dispatch)
this.setState({
props:{
...this.state.props,
...stateProps,
...dispatchProps
}
})
}
render(){
// 把数据放入
return <wrapperComponent {...this.state.props}/>
}
}
}
支持一下
扫一扫,支持poetries