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