Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。 ——react官网
虽然redux可以实现一个状态state,整个项目使用,但是有时候,该state无需全局使用,用redux工具,显得有点杀鸡用牛刀的feel,并且还可能是父组件的state,其孙组件(子组件的子组件的级别)需要使用,但若为了给孙组件一个状态值,每一层组件都向下传递一个props且不使用,未免就太没必要了,因此context的表现时刻就到了。
需求
创建白天黑夜主题切换项目
创建components文件夹,新建两个样式组件Navbar.js 和 BookList.js
创建contexts文件夹,里面新建 ThemContext.js,用于存放主题切换的状态
import React, { Component, createContext } from 'react'
// 创建 context上下文
export const ThemContext = createContext()
class ThemContextProvider extends Component {
state = {
them: true,
lightThem: {background: '#333', color: '#fff'},
darkThem: {background: '#fff', color: '#333'}
}
render() {
return (
// 使用 Provider提供给子组件 数据
<ThemContext.Provider value={{...this.state }}>
{/* 包裹子组件 */}
{this.props.children}
</ThemContext.Provider>
)
}
}
export default ThemContextProvider
在App.js中一块引入
import BookList from './component/BookList';
import Navbar from './component/Navbar'
import ThemContextProvider from './contexts/ThemContext'
function App() {
return (
<div className="App">
{/* 使用context组件 将子组件进行包裹 */}
<ThemContextProvider>
<Navbar />
<BookList />
</ThemContextProvider>
</div>
);
}
export default App;
以上该context组件就已经包裹了需要的子组件,下面我们需要在子组件中获取context对象
子组件中获取context的方法一: contextType 方法
// Navbar .js
import React, { Component } from 'react'
import { ThemContext } from '../contexts/ThemContext'
export default class Navbar extends Component {
// React 会往上找到最近的 theme Provider,然后使用它的值
static contextType = ThemContext
render() {
console.log(this.context)
const { them, lightThem, darkThem } = this.context
const themType = them ? lightThem : darkThem
return (
<nav className="navbar" style={{background: themType.background, color: themType.color}}>
<ul>
<li>HOME</li>
<li>ABOUT</li>
<li>CONTACT</li>
</ul>
</nav>
)
}
}
子组件中获取context的方法一: Consumer方法
import React, { Component } from 'react'
import { ThemContext } from '../contexts/ThemContext'
export default class BookList extends Component {
render() {
return (
// Consumer方法 后面接一个函数
<ThemContext.Consumer>{(context) => {
const { them, lightThem, darkThem } = context
const themType = them ? lightThem : darkThem
return (
<div className="book-list" style={{background: themType.background, color: themType.color}}>
<ul>
<li style={{background: themType.background, color: themType.color}}>《我是好书》</li>
<li style={{background: themType.background, color: themType.color}}>《我是一本书》</li>
<li style={{background: themType.background, color: themType.color}}>《我是书》</li>
</ul>
</div>
)
}}
</ThemContext.Consumer>
)
}
}
以上便是子组件中获取context的两种方法,他们的区别是什么呢?
总结
contextType vs Consumer(推荐)
1.前者contextType 只能获取单一(一个)context上下文,而Consumer可以获取多个context
2.Consumer在类创建的组件或者函数创建的组件都可以使用,而contextType 只能在类创建的组件使用(因为contextType 需要static关键词)