上下文
上下文允许您将一个值传递给树中很深的子级,而无需通过中间的每个组件通过道具传递它。一个非常流行的用例是主题。简而言之,上下文可以被认为是在 Preact 中执行发布-订阅式更新的一种方式。
有两种不同的方式来使用上下文:通过较新的 createContext API 和旧版上下文 API。两者的区别在于,旧版 API 无法在中间组件通过 shouldComponentUpdate 中止渲染时更新子级。这就是我们强烈建议始终使用 createContext 的原因。
createContext
首先,我们需要创建一个我们可以传递的上下文对象。这是通过 createContext(initialValue) 函数完成的。它返回一个 Provider 组件,用于设置上下文值,以及一个 Consumer 组件,用于从上下文中检索值。
initialValue 参数仅在上下文在树中上方没有匹配的 Provider 时使用。这可能有助于单独测试组件,因为它避免了创建包装 Provider 的需要。
const Theme = createContext('light');
function ThemedButton(props) {
  return (
    <Theme.Consumer>
      {theme => {
        return <button {...props} class={'btn ' + theme}>Themed Button</button>;
      }}
    </Theme.Consumer>
  );
}
function App() {
  return (
    <Theme.Provider value="dark">
      <SomeComponent>
        <ThemedButton />
      </SomeComponent>
    </Theme.Provider>
  );
}
使用上下文的一种更简单的方法是通过 useContext 挂钩。
旧版上下文 API
我们主要出于向后兼容性的原因而包含旧版 API。它已被 createContext API 取代。旧版 API 已知的问题包括如果中间组件在 shouldComponentUpdate 中返回 false,则会阻止更新。如果您仍然需要使用它,请继续阅读。
要通过上下文传递自定义变量,组件需要有 getChildContext 方法。在那里,您可以返回要存储在上下文中的新值。可以通过函数组件中的第二个参数或基于类的组件中的 this.context 访问上下文。
function ThemedButton(props, context) {
  return (
    <button {...props} class={'btn ' + context.theme}>
      Themed Button
    </button>
  );
}
class App extends Component {
  getChildContext() {
    return {
      theme: 'light'
    }
  }
  render() {
    return (
      <div>
        <SomeOtherComponent>
          <ThemedButton />
        </SomeOtherComponent>
      </div>
    );
  }
}