小编典典

在React应用程序中拥有服务

reactjs

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

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

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

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


阅读 337

收藏
2020-07-22

共1个答案

小编典典

第一个答案并不反映当前的Container vs Presenter范例。

如果您需要执行某些操作(例如验证密码),则可以使用执行此操作的功能。您将把该函数作为道具传递给可重用的视图。

货柜

因此,正确的方法是编写一个ValidatorContainer,它将具有该功能的属性,并将其包装在其中,然后将正确的道具传递给孩子。当涉及到视图时,验证器容器将包装您的视图,而视图将使用容器逻辑。

验证可以全部在容器的属性中完成,但是如果您使用的是第三方验证器或任何简单的验证服务,则可以将该服务用作容器组件的属性,并在容器的方法中使用它。我已经为宁静的组件完成了此任务,并且效果很好。

提供者

如果需要更多配置,则可以使用提供者/消费者模型。提供程序是一个高级组件,它包装在顶层应用程序对象(您安装的对象)附近和下方,并将其自身的一部分或在顶层配置的属性提供给上下文API。然后,我将容器元素设置为使用上下文。

父/子上下文关系不必彼此靠近,只是必须以某种方式将子代降落。Redux存储和React
Router以这种方式起作用。我用它为我的rest容器提供了一个根源的rest上下文(如果我不提供自己的)。

(请注意:上下文API在文档中被标记为实验性的,但考虑到正在使用的内容,我认为它不再适用了)。

//An example of a Provider component, takes a preconfigured restful.js

//object and makes it available anywhere in the application

export default class RestfulProvider extends React.Component {

    constructor(props){

        super(props);



        if(!("restful" in props)){

            throw Error("Restful service must be provided");

        }

    }



    getChildContext(){

        return {

            api: this.props.restful

        };

    }



    render() {

        return this.props.children;

    }

}



RestfulProvider.childContextTypes = {

    api: React.PropTypes.object

};

中间件

我没有尝试过但被使用过的另一种方法是将中间件与Redux结合使用。您可以在应用程序外部或至少高于redux存储区定义服务对象。在商店创建期间,您将服务注入到中间件中,并且中间件处理影响服务的所有操作。

这样,我可以将我的restful.js对象注入中间件,并用独立的动作替换我的容器方法。我仍然需要一个容器组件来提供对表单视图层的操作,但是connect()和mapDispatchToProps让我覆盖了那里。

例如,新的v4 react-router-redux使用此方法来影响历史记录的状态。

//Example middleware from react-router-redux

//History is our service here and actions change it.



import { CALL_HISTORY_METHOD } from './actions'



/**

 * This middleware captures CALL_HISTORY_METHOD actions to redirect to the

 * provided history object. This will prevent these actions from reaching your

 * reducer or any middleware that comes after this one.

 */

export default function routerMiddleware(history) {

  return () => next => action => {

    if (action.type !== CALL_HISTORY_METHOD) {

      return next(action)

    }



    const { payload: { method, args } } = action

    history[method](...args)

  }

}
2020-07-22