情景:3个组件,A包含B,B包含C,A组件通过context向C传参
代码实现如下,包含类组件写法、函数组件普通写法、函数组件hook写法
import React, { Component, useContext } from 'react'
import styles from './index.less'
// 第一步,创建一个context容器对象
const MyContext = React.createContext('')
export default class A extends Component {
state = { username: 'Wsh' }
render() {
return (
<div className={styles.root}>
<h3>我是A组件</h3>
<h4>我的用户名是:{this.state.username}</h4>
<button onClick={() => { this.setState({ username: 'Yj' }) }}>点击修改name</button>
{/* 第二步,使用Provider向下传递value */}
<MyContext.Provider value={this.state.username}>
<B username={this.state.username} />
</MyContext.Provider>
</div>
)
}
}
class B extends Component<any> {
render() {
return (
<div className='b'>
<h3>我是B组件</h3>
<h4>我从A接收到的用户名是:{this.props.username}</h4>
<C />
</div>
)
}
}
/**
* 这种方式只有类组件可使用,且一个类组件只能设置一个contextType
*/
// class C extends Component {
// // 声明接收context
// static contextType = MyContext
// render() {
// return (
// <div className='c'>
// <h3>我是C组件</h3>
// <h4>我从A接收到的用户名是:{this.context}</h4>
// </div>
// )
// }
// }
/**
* 这种方式类组件和函数组件都能用,但是不够简洁
*/
// const C = () => {
// return (
// <div className='c'>
// <h3>我是C组件</h3>
// <h4>我从A接收到的用户名是:
// {/* 第三步,使用Consumer来接收value */}
// <MyContext.Consumer>
// {value => value}
// </MyContext.Consumer>
// </h4>
// </div>
// )
// }
/**
* 这种方式为函数组件hook写法,简洁且可使用多个context
*/
const C = () => {
const value = useContext(MyContext)
return (
<div className='c'>
<h3>我是C组件</h3>
<h4>我从A接收到的用户名是:{value}</h4>
</div>
)
}
通常我们需要在不同的文件中引用同一个上下文,所以一般在单独的文件中声明:
// Contexts.js
import { createContext } from 'react';
export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);