Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
为什么需要 Context?
在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树逐层传递 props。
注意: 在 ReScript 中, 由于其 JSX prop 双关 功能和强大的类型推导,传递 props 属性要比 TS / JS 中简单得多,所以最好保持简单,只做 props 传递。Less magic means more transparency!
何时使用 Context
Context 的设计目的是为了在整个组件树中共享“全局”数据,例如当前认证的用户、主题或首选语言。举个例子,在下面的代码中,我们通过一个 “theme” 属性手动调整一个按钮组件的样式:
// src/App.res
type theme = Light | Dark;
module Button = {
@react.component
let make = (~theme) => {
let className = switch theme {
| Light => "theme-light"
| Dark => "theme-black"
};
<button className> {React.string("Click me")} </button>
}
}
module ThemedButton = {
@react.component
let make = (~theme) => {
<Button theme />
}
}
module Toolbar = {
@react.component
let make = (~theme) => {
<div>
<ThemedButton theme/>
</div>
}
}
@react.component
let make = () => {
// // We define the theme in the
// // toplevel App component and
// // pass it down
// 我们在顶层的 App 组件定义 theme 属性
// 并将其向下传递
<Toolbar theme=Dark/>
}
使用 context, 我们可以避免通过中间元素传递 props:
// src/App.res
module ThemeContext = {
type theme = Light | Dark;
let context = React.createContext(Light)
module Provider = {
let provider = React.Context.provider(context)
@react.component
let make = (~value, ~children) => {
React.createElement(provider, {"value": value, "children": children})
}
}
}
module Button = {
@react.component
let make = (~theme) => {
let className = switch theme {
| ThemeContext.Light => "theme-light"
| Dark => "theme-black"
};
<button className> {React.string("Click me")} </button>
}
}
module ThemedButton = {
@react.component
let make = () => {
let theme = React.useContext(ThemeContext.context)
<Button theme/>
}
}
module Toolbar = {
@react.component
let make = () => {
<div> <ThemedButton /> </div>
}
}
@react.component
let make = () => {
<ThemeContext.Provider value=ThemeContext.Dark>
<div> <Toolbar /> </div>
</ThemeContext.Provider>
}