context 基本使用
context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。context 对象提供两个组件,Provider
和 Consumer
作为提供者和消费者,但是必须注意一点是,提供者永远要在消费者上层,正所谓水往低处流,提供者一定要是消费者的某一层父级。
1.createContext 创建
const GlobalContext = React.createContext(null) //
const GlobalProvider = GlobalContext.Provider //提供者
const GlobalConsumer = GlobalContext.Consumer // 订阅消费者
export const GlobalContext = React.createContext<IGlobalContext>({
logged: false,
abTest: "A",
});
return (
<>
<GlobalContext.Provider value={{ logged, abTest }}>
<Routes />
</GlobalContext.Provider>
</>
);
类组件之contextType 方式 获取
class Leaf extends Component {
static contextType = GlobalContext;
render() {
const battery = this.context;
return<h1>Battery : {battery}</h1>
}
}
- contextType为静态属性;
- this.context就可以获取context属性值了
- contextType 只能在类组件中使用
- 一个组件如果有多个 consumer , contextType 只对其中一个有效,所以说,contextType 只能有一个
函数组件之 useContext 方式 获取
useContext 接受一个参数,就是想要获取的 context ,返回一个 value 值,就是最近的 provider 提供 contextValue 值。
import { useContext } from "react";
import { GlobalContext } from "@/pages";
/**
* @return abTest AbTest状态
*/
function useAbTest(): string {
const { abTest } = useContext(GlobalContext);
return abTest;
}
export default useAbTest;
订阅者之 Consumer 方式 获取
- Consumer 订阅者采取 render props 方式,接受最近一层 provider 中value 属性,作为 render props 函数的参数,可以将参数取出来,作为 props 混入
ConsumerDemo
组件,说白了就是 context 变成了 props。
class Bottom extends React.Component {
render () {
return (
// Context.Consumer Consumer消费者使用Context得值
// 但子组件不能是其他组件,必须渲染一个函数,函数的参数就是Context得值
<GlobalContext.Consumer>
{
({logged,abTest}) => <h1>GlobalContext 的 值为 {logged},{abTest}</h1>
}
</GlobalContext.Consumer>
)
}
}
context 作用
context解决了:
- 解决了 props 需要每一层都手动添加 props 的缺陷。
- 解决了改变 value ,组件全部重新渲染的缺陷。
react-redux 就是通过 Provider 模式把 redux 中的 store 注入到组件中的。
context 小技巧
- 嵌套 Provider
- 逐层传递Provider
- 全局只有一个 ThemeContext ,两次用 provider 传递两个不同 context 。
- 组件获取 context 时候,会获取离当前组件最近的上一层 Provider 。
- 下一层的 provider 会覆盖上一层的 provider 。
3.context中还可以传递方法
export default function (){
const [ themeContextValue ,setThemeContext ] = React.useState(theme.dark)
/* 传递颜色主题 和 改变主题的方法 */
return <ThemeContext.Provider value={ { ...themeContextValue, setTheme:setThemeContext } } >
<App/>
</ThemeContext.Provider>
}