接口思维:如何使用 Context API 构建灵活、可维护的 React 组件
作者:互联网
React 文档提到 Context 旨在在组件之间共享数据共享值,而无需显式地通过树的每个级别传递 prop(prop 钻孔问题)。
Context允许父组件向其下方树中的任何组件提供一些信息——无论多深——而无需通过 props 显式传递。
要了解有关钩子的更多信息,您可以在此处下载备忘单,其中包含最常见的 React 钩子以及示例和插图。
理想情况下,您可以在上下文中放置您喜欢的任何内容,只要它们小而简洁即可。React 为您提供了可以在上下文中使用哪些数据的灵活性,这也意味着没有太多好的指导。
我想讨论一种关于在上下文中可以使用什么类型的数据的模式,以便您可以最大限度地提高 React 应用程序的灵活性。
简而言之,当您需要一些上下文时,尽可能尝试使用接口而不是实现——即使它只是一个单例(该接口的一个不太明显的实例将是一个测试模拟)。就像在 OO 世界中一样,我们会在类中使用接口,只有在运行时我们才知道应该使用哪个实现。
例如,我们需要制作Payment
支持不同国家的组件——使用不同的汇总逻辑并显示不同的货币符号。例如,在日本,四舍五入到最接近的百位更有意义。
所以在这种情况Payment
下,组件应该依赖于一个PaymentStrategy
接口,在 React 树的更高级别,我们可以“注入”该接口的不同实例,并且保持Payment
自身不变。
介绍界
接口定义的代码片段可以是:
接口 PaymentStrategy { getCurrencySign(): string; getCurrencySign (): 字符串; roundUp(数量:数量):数量; }
在不同的国家,你可以实现这样的逻辑:
AustralianStrategy 类实施 PaymentStrategy { getCurrencySign ( ) { return "$" ; } roundUp(金额:数字){ 返回 数学。地板(数量+ 1) } }
所以在你的实际Payment
组件中,我们可以使用这样的接口:
const Payment = ( {amount, strategy}: {amount: number , strategy: PaymentStrategy} ) => { return <button>{strategy.roundUp(amount)}</button>; } }
这种方法效果很好,唯一的缺点是当我们使用 时Payment
,我们需要PaymentStrategy
在调用站点附近的某个地方定义一个新的。
const strategy = new AustralianStrategy (); const CheckoutPage = ( ) => { //... return ( <Payment amount={amount} strategy={strategy} /> ) }
该代码有点不反应。稍加改动就可以使代码更易于维护——使用 Context API。
使用反应上下文
在树的更高层,通常在应用程序根目录中,我们可以设置许多上下文。这些上下文都是正交的,这意味着它们不重叠。一个用于安全审计,一个用于日志记录,另一个用于某些业务逻辑切换。
我们可以利用国家代码来切换不同的策略:
// PaymentStrategyContext.tsx 导出 接口 PaymentStrategyContextType { strategy : PaymentStrategyContext ; } 导出 默认createContext< PaymentStrategyContextType | 空>(空);
并在应用程序设置中:
从“./PaymentStrategyContext”导入PaymentStrategyContext ;const App = ( ) => { // 或从工厂获取不同国家/地区的不同策略const strategy = new AustralianStrategy (); 返回( <LoggingContext.Provider> <PaymentStrategyContext.Provider value={{strategy}}> <Route {...} /> </PaymentStrategyContext.Provider> </LoggingContext.Provider> ) }
最后,我们的Pyament
组件将获取从应用程序根传入的任何内容。
const Payment = ( {amount}: {amount: number } ) => { const {strategy} = useContext ( PaymentStrategyContext ); 返回<button>{strategy.roundUp(amount)}</button>; }
而且它也很容易测试。如果您使用的是react-testing-library
,只需使用策略接口的虚假实现定义自定义呈现就足够了。(我在这篇长篇文章中详细讨论了这种模式)
将接口与 Context API 结合使用的好处是:
- 增加灵活性:当您想到接口时,您是在组件之间定义一个契约,允许它们在不知道彼此实现细节的情况下进行交互。这使得更改或更新组件的实现变得更加容易,而不会影响依赖它的其他组件。
- 更好的封装:通过为您的组件定义接口,您可以隐藏它们的内部细节并仅公开公共 API。这有助于控制代码的复杂性并使其更易于推理。
- 更容易维护:当你想到接口时,你会创建模块化和可重用的组件,随着时间的推移更容易维护。如果你需要更新一个组件,你可以这样做而不用担心破坏依赖它的其他组件。
- 更好的可测试性:通过为您的组件定义接口,您可以编写专注于公共 API 而忽略内部细节的测试。这使得编写涵盖所有边缘情况的综合测试变得更加容易,并确保您的代码按预期工作。
概括
使用 Context 共享数据并采用面向接口的方法可以释放出比数据共享更多的好处。尽管乍一看似乎更复杂,但在接口中思考可以增强代码的灵活性和可维护性。本质上,接口提供组件之间的契约,允许更容易的更改和更新、更好的封装和改进的可测试性。
标签:编程,Context API,React 来源: