context出现的缘由:react中,数据都是自顶而下的传递方式,如果在顶层state中存储数据,如果在不借助第三方的状态管理框架的情况下,想要在自组件中过去数据,就必须一层层传递下去,但是有时候传递的某些层级的中用不到这些数据,这时候层级越深越可怕。
正式因为有了上面的这种场景,官方提供了context机制,通过context就可以在自组件里获取祖先组件里的值,而不需层层传递,在react16.3之前context只是官方的实验性API,官方是不推荐开发者使用的,由于有很多开发者使用,所以官方在react16.3版本中发布了最新的context API,新的API,更加易用。
在新的context API中 React提供了一个createContext的方法,该方法返回了一个包含Provider,Consumer对象
举个例子:
// content.jsx
import { createContext } from 'react';
// createContext:用来创建context,有一个参数是默认值,返回值是Provider和Consumer对象
// Provider:用于提供context组件
// Consumer:用于获取context组件
export const { Provider, Consumer } = createContext({ a:1 })
在App.jsx顶层组件中的使用Provider,同时传递一个value进去。
// App.jsx
import React, { Component } from 'react';
import { Provider } from './content'
import Parent from "./parent"
class App extends Component{
state = { a: 2 };
render() {
return (
<div>
<Provider value={this.state} >
<Parent/>
</Provider>
</div>
)
}
}
export default App;
在child组件中利用Consumer就可以获取到App中传递的数据,Consumer需要使用一个函数作为子元素来接受传递的数据,函数的参数就是上面传递下来的数据。
// child.js
import React, { PureComponent } from 'react';
import { Consumer } from './content'
class Child extends PureComponent{
render(){
return (
<Consumer>
{context => <p>{context.a}</p>}
</Comsumer>
)
}
}
export default Child
上面的三个文件的数据流传递关系:App -> Parent -> Child 这样我们在顶层的数据,就可以在child这个自组件中获取到。
注意:只有在上层组件没有提供Provider组件的时候,下层组件Consumer才会直接使用createContext函数中的那个初始化参数。但是如果有Consumer组件,但是value没有值或者值是undefind/null也是不会使用初始化参数的
react context 到 React-redux的进化
当我们要传递的数据变多的场景中,都要调用Consumer的话,会显得很冗余,所以我们要将Consumer封装起来。
import React from 'react';
import { Consumer } from './context'
export default mapState => {
return WrappedComponent => {
const Component = props => (
<Consumer>
{
value => {
let mappedProps = mapState(value);
return <WrappedComponent {...props} {...mappedProps}/>
}
}
</Consumer>
);
Component.displayName = `connect(${WrappedComponent.displayName || WrappedComponent.name || "Component"})`;
return Component
}
}
connect方法传传入一个mapState方法,mapState是context的value映射方法,当调用connect方法后吗,会返回一个高阶函数工厂,将传入的WrappedComponent组件用Comsumer包裹住,获取到Comsumer中传递过来的value,计算出最终的mappedProps属性,然后把mappedProps传递给组件WrappedComponent。
引用:
- https://blog.csdn.net/jjx0224/article/details/88242842
- https://github.com/reduxjs/react-redux
- https://www.redux.org.cn/docs/react-redux/api.html