长话短说:
1、官网
https://react.docschina.org/docs/context.html
2、优点
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
3、问题
Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。
4、函数组件 使用
context.jsx
import { createContext } from "react";
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee'
},
dark: {
foreground: '#ffffff',
background: '#aaaaaa'
}
};
export const ThemeContext = createContext(themes.light)
export const CompAContext = createContext()
index.jsx
import React from 'react';
import { ThemeContext, themes } from './context';
import CompA from './selfComp/CompA';
import CompB from './selfComp/CompB';
import './index.less';
function Context () {
return (
<div>
<ThemeContext.Provider value={themes.dark}>
组件A:
<CompA/>
<br/><br/>
------
<br/><br/>
组件B:
<CompB/>
</ThemeContext.Provider>
</div>
)
}
export default Context;
CompA.jsx
import React from 'react';
import { CompAContext } from '../context';
import CompAA from './CompAA';
function CompA () {
return (
<div>
<CompAContext.Provider value={'This is CompA'}>
<CompAA />
</CompAContext.Provider>
</div>
)
}
export default CompA;
CompAA.jsx
import React,{useContext} from 'react';
import { CompAContext,ThemeContext } from '../context';
function CompAA () {
const val = useContext(CompAContext)
const themes = useContext(ThemeContext)
return (
// 1、使用useContext
<>
<div style={{background: themes.background, color:themes.foreground}}>CompAA</div>
<div>{'CompAA ------' + val}</div>
</>
// 2、CompAContext.Consumer
// <div>
// <CompAContext.Consumer>
// {
// (val) => (
// <ThemeContext.Consumer>
// {
// themes => (
// <>
// <div style={{background: themes.background, color:themes.foreground}}>CompAA</div>
// <div>{'CompAA ------' + val}</div>
// </>
// )
// }
// </ThemeContext.Consumer>
// )
// }
// </CompAContext.Consumer>
// </div>
)
}
export default CompAA;
CompB.jsx
import React,{useContext} from 'react';
import { ThemeContext } from '../context';
function CompB () {
const themes = useContext(ThemeContext)
return (
// 1、useContext
<div style={{background: themes.background, color:themes.foreground}}>CompB</div>
// 2、Consumer
// <div>
// <ThemeContext.Consumer>
// {
// (themes) => (
// <div style={{background: themes.background, color:themes.foreground}}>CompB</div>
// )
// }
// </ThemeContext.Consumer>
// </div>
)
}
export default CompB;
总结:
Provider后,子组件中有两种接收值的方法:(详细见上面案例)
1、使用 Consumer
2、使用 useContext
目录结构
效果
其他:
1、类组件使用(以 CompB 为例)
class CompB extends React.Component {
componentDidMount() {
let themes = this.context;
/* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
}
componentDidUpdate() {
let themes = this.context;
/* ... */
}
componentWillUnmount() {
let themes = this.context;
/* ... */
}
render() {
let themes = this.context;
/* 基于 MyContext 组件的值进行渲染 */
<div style={{background: themes.background, color:themes.foreground}}>CompB</div>
}
}
CompB.contextType = ThemeContext;
2、如果你正在使用实验性的 public class fields 语法,你可以使用 static
这个类属性来初始化你的 contextType
。
class CompB extends React.Component {
static contextType = ThemeContext;
render() {
let themes = this.context;
/* 基于这个值进行渲染工作 */
<div style={{background: themes.background, color:themes.foreground}}>CompB</div>
}
}