编程语言
首页 > 编程语言> > 接口思维:如何使用 Context API 构建灵活、可维护的 React 组件

接口思维:如何使用 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 结合使用的好处是:

  1. 增加灵活性:当您想到接口时,您是在组件之间定义一个契约,允许它们在不知道彼此实现细节的情况下进行交互。这使得更改或更新组件的实现变得更加容易,而不会影响依赖它的其他组件。
  2. 更好的封装:通过为您的组件定义接口,您可以隐藏它们的内部细节并仅公开公共 API。这有助于控制代码的复杂性并使其更易于推理。
  3. 更容易维护:当你想​​到接口时,你会创建模块化和可重用的组件,随着时间的推移更容易维护。如果你需要更新一个组件,你可以这样做而不用担心破坏依赖它的其他组件。
  4. 更好的可测试性:通过为您的组件定义接口,您可以编写专注于公共 API 而忽略内部细节的测试。这使得编写涵盖所有边缘情况的综合测试变得更加容易,并确保您的代码按预期工作。

概括

使用 Context 共享数据并采用面向接口的方法可以释放出比数据共享更多的好处。尽管乍一看似乎更复杂,但在接口中思考可以增强代码的灵活性和可维护性。本质上,接口提供组件之间的契约,允许更容易的更改和更新、更好的封装和改进的可测试性。

标签:编程,Context API,React
来源: