上下文
上下文允许你直接传值到组件树下方,无需使用 prop 通过中间组件传递。主题是一个最常用的的用例。简而言之,可以将上下文看作 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}>主题按钮</button>;
}}
</Theme.Consumer>
);
}
function App() {
return (
<Theme.Provider value="dark">
<SomeComponent>
<ThemedButton />
</SomeComponent>
</Theme.Provider>
);
}
Run in REPL另一种使用 Context 的简单方法是使用 useContext 钩子。
旧版上下文 API
处于向后兼容我们仍提供此旧版 API,它已经被 createContext
API 取代。此 API 在中间组件的 shouldComponentUpdate
方法返回 false
时会出现阻塞更新问题。若您仍需要此方法,请继续阅读。
组件需要实现 getChildContext
才能通过上下文传递自定义变量,你可以在此方法内返回想在上下文中存储的值。然后可以通过函数组件的第二个参数或类组件的 this.context
获取存储的值。
function ThemedButton(props, context) {
return (
<button {...props} class={'btn ' + context.theme}>
主题按钮
</button>
);
}
class App extends Component {
getChildContext() {
return {
theme: 'light'
}
}
render() {
return (
<div>
<SomeOtherComponent>
<ThemedButton />
</SomeOtherComponent>
</div>
);
}
}
Run in REPL