Context 给整个组件树共享全局数据的
有全局,就一定会出现污染和复用性的问题
- 简单城市选择器的例子
import React, { Component } from 'react'
const CityContext = React.createContext({
name: 'lingling',
text: '零陵'
})
class Select extends Component {
/**
* 将上下文的类型指定为 CityContext
* this.context -> this.state.cityInfo
* 向上找最近的CityContext的Provider,并且取值 cityInfo
*/
static contextType = CityContext//但是这种东西其实是对组件进行污染了
render() {
return (
<select
value={this.context.name}
onChange={(e) => this.props.changeCity({
name: e.target.value,
text: e.target[e.target.selectedIndex].text//获取的内容
})}
>
<option value="beijing">北京</option>
<option value="chengdu">成都</option>
<option value="shenzhen">深圳</option>
<option value="lingling">零陵</option>
</select>
)
}
}
class Header extends Component {
render() {
return (
<Select changeCity={this.props.changeCity} />
)
}
}
export default class App extends Component {
state = {
cityInfo: {
name: 'lingling',
text: '零陵'
}
}
changeCity(cityInfo) {
this.setState({ cityInfo })
}
render() {
return (
<CityContext.Provider value={this.state.cityInfo}>
<Header changeCity={this.changeCity.bind(this)} />
<span>{this.state.cityInfo.text}</span>
</CityContext.Provider>
)
}
}
总结
- 最适合的场景:杂乱无章的组件都需要同一些数据的时候,层级过多的时候
- 单纯为了不层层传递属性,Context 实际上是不合适(组件是要有纯度的,复用性不好)
- Context的弱点: 弱化及污染组件的纯度,度导致组件的复用性降低
- 上述的 Select组件如果只做城市选择的话,static contextType = CityContext就没啥问题
- 但是如果是通用的选择器的话,就不行了
思考并处理上述的问题
- 通过组合组件的方式来处理,就不用一层层搞了
- 就是通过把组件当作属性传给子元素
- 这种的方式更加清晰,不需要和上面的Header组件中再去传递一次prop,可以直接给App来做的
import React, { Component } from 'react'
class Selector extends Component {
render() {
return (
<select
defaultValue={this.props.cityInfo.name}
onChange={(e) => this.props.changeCity({
name: e.target.value,
text: e.target[e.target.selectedIndex].text//获取的内容
})}
>
{
this.props.cityData.map((item, index) => {
return <option value={item.value} key={index}>{ item.text }</option>
})
}
</select>
)
}
}
class Header extends Component {
render() {
return (
<header>
<h1>{this.props.text}</h1>
<div>{ this.props.citySelector }</div>
</header>
)
}
}
export default class App extends Component {
state = {
headerTitle: '标题',
cityInfo: {
name: 'lingling',
text: '零陵'
},
cityData: [
{name: 'beijing', text: '北京'},
{name: 'shenzhen', text: '深圳'},
{name: 'lingling', text: '零陵'},
]
}
changeCity(cityInfo) {
this.setState({
cityInfo
})
}
render() {
return (
<>
<Header
text={this.state.headerTitle}
citySelector={
<Selector
cityData={this.state.cityData}
cityInfo={this.state.cityInfo}
changeCity={this.changeCity.bind(this)}
></Selector>
}
></Header>
<span>{ this.state.cityInfo.text }</span>
</>
)
}
}
结论
- react的组件尽量扁平化层级不要太深,会方便对数据的传递
- Context使用适可而止看场景使用吧