Context是什么
- 我们知道,在React中数据是通过
props
属性自上而下传递的,而且每次传只能一层;如果在最底层的组件想要获得在最顶层组件传下来的数据或方法,你就得在他们之间的每个组件上通过props
层层传递。
如果有十几层嵌套,我裂开了。。。 - 幸亏,有了react-redux,我们得救了。稍微深入一点,就会发现他是通过
React
中的 Context
结合Redux
来实现的
Context怎么用
- 代码结构
- 渲染视图
源码如下
import React from 'react'
import ReactDOM from 'react-dom';
import {MyContext} from './myContext.js'
import Children from './children.js'
import Children02 from './children02.js'
class App extends React.Component {
constructor(props){
super(props)
this.state = {
data:{
mydata:'来自App的值'
}
}
}
handleChange = (v) => {
this.setState({
...this.state,
data:{
mydata:'更新后的值' + v
}
})
}
render() {
return (
<div>
包裹在 Providor 中
<MyContext.Provider value={this.state} >
<Children />
<Children02 handleChange={this.handleChange}/>
</MyContext.Provider>
<br /><hr />
不会触发视图更新,React是感知不到数据的变化的,因为他是在myContext.js里一个普通的,并没有被React追踪,只有自己强制更新才行<br/>
(你可以在dev tool里看到下面两个组件的Context属性同步变化了,但是视图不会更新)
未包裹在 Providor 中<br/>
<Children />
<Children02 />
<button onClick={() => this.forceUpdate()}>强制更新</button>
在Providor中包裹的组件和没在包裹之中的组件是会维持各自的数据的,MyContext.Provider相当于充当了里面消费组件的数据源,而没有被包裹的就会使用myContext里面的默认的数据
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
- childre.js
这个组件是通过Children.contextType = MyContext;
的形式来消费Providor提供的数据
import React from 'react'
import {MyContext} from './myContext.js';
class Children extends React.Component {
render() {
let v = this.context;
return (
<div>
<h2>Children: {v.data.mydata} </h2>
</div>
);
}
}
Children.contextType = MyContext;
export default Children;
- children02.js
这个组件是通过<MyContext.Consumer> {(value) => {//....}} </MyContext.Consumer>
的形式来消费Providor提供的数据
import React from 'react'
import {MyContext} from './myContext.js';
class Children02 extends React.Component {
constructor(props){
super(props)
this.state = {
value: ''
}
}
render() {
return (
<MyContext.Consumer>
{(v) => (
<div>
<h3>Children02:{v.data.mydata}</h3>
<input type='input'
onChange= { (e) => {
this.props.handleChange ?
this.props.handleChange(e.target.value)
: v.handleChange(e.target.value)
}
}
>
</input>
</div>
)}
</MyContext.Consumer>
);
}
}
export default Children02;
import React from 'react'
const handleChange = (v) => {
defalutValue.data.mydata = v
}
var defalutValue = {
data:{
mydata:'这是默认值(来自myContext.js)'
},
handleChange
}
export const MyContext = React.createContext(defalutValue);