帮助
支持我们

上下文

上下文允许您将一个值传递给树中很深的子级,而无需通过中间的每个组件通过道具传递它。一个非常流行的用例是主题。简而言之,上下文可以被认为是在 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>
  );
}
在 REPL 中运行

使用上下文的一种更简单的方法是通过 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>
    );
  }
}
在 REPL 中运行