React Context 跨级传参
Context 提供了一个局部的全局作用域,使用 Context 则无需再手动的逐层传递 props。
一、Context 的使用
1、createContext + contextType
可以通过 Class.contextType 直接将 Context 对象挂载到 class 的 contextType 属性,然后就可以使用 this.context 对 context 对象进行使用。举个设置主题 theme 的例子:
- 使用 Context 前:
import React from 'react'
const Father = () => {
return <Child theme="dark" />
}
const Child = (props) => {
return <GrandChild theme={props.theme} />
}
class GrandChild extends React.Component {
render() {
return <div>{this.props.theme}</div>
}
}
export default Father
- 使用 Context 后:
import React from 'react'
// 为 theme 创建一个 Context(默认值为 light)
const ThemeContext = React.createContext('light')
const Father = () => {
// 使用 Provider 将当前的 theme 传递给以下的组件树
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
)
}
// 中间的组件就不用层层往下传递 theme 了
const Child = () => {
return <GrandChild />
}
class GrandChild extends React.Component {
// 指定 contextType 读取当前的 theme context
// React 会往上找到最近的 theme Provider,然后使用它的值 dark
static contextType = ThemeContext
render() {
return <div>{this.context}</div>
}
}
export default Father
2、createContext + Consumer
当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 Consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 Consumer 组件在其祖先组件退出更新的情况下也能更新。
import React from 'react'
const ThemeContext = React.createContext('light')
const Father = () => {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
)
}
const Child = () => {
return <GrandChild />
}
const GrandChild = () => {
// 使用 Consumer 基于 context 值进行渲染
return (
<ThemeContext.Consumer>
{(value) => <div>{value}</div>}
</ThemeContext.Consumer>
)
}
export default Father
3、createContext + useContext
useContext 钩子函数接收一个 Context 对象并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider>
的 value prop 决定。
当组件上层最近的 <MyContext.Provider>
更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。
import React, { useContext } from 'react'
const ThemeContext = React.createContext('light')
const Father = () => {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
)
}
const Child = () => {
return <GrandChild />
}
const GrandChild = () => {
// 使用 useContext 引入提供的 ThemeContext
const value = useContext(ThemeContext)
return <div>{value}</div>
}
export default Father