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