在React应用程序中拥有服务

reactjs React.js

逆天ProNear

2020-03-11

我来自一个有角度的世界,在那里我可以将逻辑提取到服务/工厂,并在控制器中使用它们。

我试图了解如何在React应用程序中实现相同的目标。

假设我有一个可以验证用户密码输入(强度)的组件。它的逻辑非常复杂,因此我不想将其编写在自己的组件中。

我应该在哪里写这个逻辑?在商店中是否使用助焊剂?还是有更好的选择?

第702篇《在React应用程序中拥有服务》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

4个回答
HarryItachi蛋蛋 2020.03.11

我和你一样穿着靴子。在您提到的情况下,我会将输入验证UI组件实现为React组件。

我同意验证逻辑本身的实现不应(必须)耦合。因此,我将其放入单独的JS模块中。

也就是说,对于不应耦合的逻辑,请使用单独文件中的JS模块/类,并使用require / import将组件与“服务”分离。

这允许依赖项注入和两者的单元测试独立。

HarryL 2020.03.11

同样的情况:完成了多个Angular项目并转移到React,没有一种简单的方法可以通过DI提供服务似乎缺少了一点(除了服务的细节)。

使用上下文和ES7 decorator,我们可以接近:

https://jaysoo.ca/2015/06/09/react-contexts-and-dependency-injection/

似乎这些家伙已经朝着另一个方向迈出了一步:

http://blog.wolksoftware.com/dependency-injection-in-react-powered-inversifyjs

仍然感觉像在对抗谷物。在进行重大React项目后的6个月内,将重新讨论该答案。

编辑:6个月后,有了更多的React经验。考虑一下逻辑的性质:

  1. 它是否(仅)绑定到UI?将其移动到组件中(可接受的答案)。
  2. 它是否(仅)与状态管理联系在一起?将其移动到一个大块
  3. 绑在一起?移至单独的文件,通过选择器在组件中使用,并进行转换。

有些还可以重用HOC,但对我来说,以上内容涵盖了几乎所有用例。另外,请考虑使用鸭子扩展状态管理,以使关注点分离并以用户界面为中心。

凯Harry 2020.03.11

请记住,React的目的是更好地耦合逻辑上应该耦合的事物。如果您要设计一个复杂的“验证密码”方法,应该在哪里使用?

那么,您将需要在每次用户需要输入新密码时使用它。这可以在注册屏幕,“忘记密码”屏幕,管理员“为另一个用户重置密码”屏幕等上。

但是在任何一种情况下,它总是与某些文本输入字段相关联。这就是应该将其耦合的地方。

制作一个非常小的React组件,该组件仅由输入字段和关联的验证逻辑组成。在所有可能需要输入密码的表单中输入该组件。

这与为逻辑提供服务/工厂实质上是相同的结果,但是您将其直接耦合到输入。因此,由于它永久地绑定在一起,因此您现在无需告诉该函数在哪里查找其验证输入。

西门十三LEY 2020.03.11

当您意识到Angular服务只是一个提供一组上下文无关方法的对象时,问题变得非常简单。只是Angular DI机制使它看起来更加复杂。DI非常有用,因为它可以为您创建和维护实例,但您实际上并不需要它。

考虑一个流行的AJAX库axios(您可能已经听说过):

import axios from "axios";
axios.post(...);

它不是服务吗?它提供了一组负责某些特定逻辑的方法,并且独立于主代码。

您的示例案例是关于创建一组隔离的方法来验证您的输入(例如,检查密码强度)。有些人建议将这些方法放在组件中,这对我来说显然是一种反模式。如果验证涉及进行和处理XHR后端调用或进行复杂的计算该怎么办?您会将这种逻辑与鼠标单击处理程序和其他特定于UI的东西混合使用吗?废话。与容器/ HOC方法相同。包装您的组件只是为了添加一种方法,该方法将检查值中是否包含数字?来吧。

我将创建一个名为“ ValidationService.js”的新文件,并将其组织如下:

const ValidationService = {
    firstValidationMethod: function(value) {
        //inspect the value
    },

    secondValidationMethod: function(value) {
        //inspect the value
    }
};

export default ValidationService;

然后在您的组件中:

import ValidationService from "./services/ValidationService.js";

...

//inside the component
yourInputChangeHandler(event) {

    if(!ValidationService.firstValidationMethod(event.target.value) {
        //show a validation warning
        return false;
    }
    //proceed
}

您可以在任何地方使用此服务。如果验证规则更改,则只需要关注ValidationService.js文件。

You may need a more complicated service which depends on other services. In this case your service file may return a class constructor instead of a static object so you can create an instance of the object by yourself in the component. You may also consider implementing a simple singleton for making sure that there is always only one instance of the service object in use across the entire application.

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android