React的数据传递方式是:
- props:只能父传子
- redux:数据传递不多的时候使用会有点重
- 数据共享:context 上下文
今天来介绍第三种数据共享写法:
在v16.3之前的context只是官方的实验性API,其实官方是不推荐开发者使用的,但是架不住很多框架依旧在使用它;所以官方在v16.3发布的新的context API,新的API会更加的易用,本文也是以v16.3为准。
react@16.x 版本之前:
- 静态属性 childContextType:声明所需要的数据结构
- PropTypes (prop-types库): 来检查声明类型
- getChildContext():返回需要提供的context值
Provide 封装代码:
import PropTypes from 'prop-types'
class Provide extends React.Component{
// 1.声明:检查context共享值的类型
static childContextType = {
// 2.用PropTypes来声明context类型
store: PropTypes.object.isRequired
}
constructor(props){
// 获取传进来的参数 并赋值给store变量
super(props);
this.store = {...props}
}
// 3.返回共享值
getChildContext(){
return {
store: this.store
}
}
render(){
return (
<div>
{this.props.children}
</div>
)
}
}
父组件(提供者)代码 :通过包裹使所有子组件共享数据
import Provide from './provide';
import CustomChild from './CustomChild';
class CustomParent extends React.component{
render(){
return (
// 使用provide共享信息,所有北provide组件包括的均可以获取到共享的data信息
<Provide data={{name:"xx",sex:"男"}}>
// 子组件中会有name,sex的信息
<CustomChild/>
<CustomChild1/>
</Provide>
)
}
}
子组件(消费者)代码:通过this.context.xx 获取
class CustomChild extends React.component{
render(){
return (
<div>
共享信息:{this.context.store.name}
</div>
)
}
}
备注:
propTypes校验: 防止缺陷并规划组件使用的数据种类
prop-types库: 只在开发模式中进行类型评估,运行在生产环境不会耗费额外的精力 react@16之前是核心react库的一部分, 现在作为prop-types包单独存在
React@16 以后的版本:createContext
- React提供了一个createContext的方法,
- 该方法返回一个包含了
- Provider对象:提供者
- Consumer对象:消费者
- 该方法返回一个包含了
父组件:
import {createContext} from "react";
const defaultValue={
color: "green",
fontSize: "20px"
}
export const PrentContext = createContext(defaultValue);
render() {
return (
<div className="App">
<PrentContext.rovider value={this.state}>
<Parent/>
</PrentContext.rovider>
</div>
);
}
HOOK: useContext
Hook 是 React 16.8.0 版本增加的新特性,可以在
函数组件中使用 state以及其他的 React 特性。只能在函数组件中使用
父组件:创建+包裹
export const ContactContext = createContext({});
function parent(){
<ContactContext.Provider value={{ itemData: res }} >
<ShowName />
<ShowSex/>
</ContactContext.Provider>
}
子组件接收数据:useContext(父定义的context)
const ShowName = () => {
const {itemData:{name}} = useContext(ContactContext);
return (
<span className='name'>{name}</span>
)
}
接受最近一层 provider中的value属性