在 React 应用程序中提供服务 [英] Having services in React application

查看:35
本文介绍了在 React 应用程序中提供服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm coming from the angular world where I could extract logic to a service/factory and consume them in my controllers.

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

I'm trying to understand how can I achieve the same in a React application.

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

Let's say that I have a component that validates user's password input (it's strength). It's logic is pretty complex hence I don't want to write it in the component it self.

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

Where should I write this logic? In a store if I'm using flux? Or is there a better option?

推荐答案

第一个答案没有反映当前的Container vs Presenter 范式.

The first answer doesn't reflect the current Container vs Presenter paradigm.

如果您需要执行某些操作,例如验证密码,您可能会有一个函数来执行此操作.你会将该函数作为道具传递给你的可重用视图.

If you need to do something, like validate a password, you'd likely have a function that does it. You'd be passing that function to your reusable view as a prop.

因此,正确的做法是编写一个 ValidatorContainer,它将该函数作为一个属性,并将表单包装在其中,将正确的道具传递给孩子.当涉及到您的视图时,您的验证器容器包装您的视图,并且该视图使用容器逻辑.

So, the correct way to do it is to write a ValidatorContainer, which will have that function as a property, and wrap the form in it, passing the right props in to the child. When it comes to your view, your validator container wraps your view and the view consumes the containers logic.

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

Validation could be all done in the container's properties, but it you're using a 3rd party validator, or any simple validation service, you can use the service as a property of the container component and use it in the container's methods. I've done this for restful components and it works very well.

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

If there's a bit more configuration necessary, you can use a Provider/Consumer model. A provider is a high level component that wraps somewhere close to and underneath the top application object (the one you mount) and supplies a part of itself, or a property configured in the top layer, to the context API. I then set my container elements to consume the context.

父/子上下文关系不必彼此靠近,只是子必须以某种方式下降.Redux 以这种方式存储和 React Router 功能.我已经用它为我的休息容器提供了一个根宁静的上下文(如果我不提供我自己的).

The parent/child context relations don't have to be near each other, just the child has to be descended in some way. Redux stores and the React Router function in this way. I've used it to provide a root restful context for my rest containers (if I don't provide my own).

(注意:上下文 API 在文档中被标记为实验性的,但考虑到它的用途,我认为它不再是了).

(note: the context API is marked experimental in the docs, but I don't think it is any more, considering what's using it).

//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 存储.在商店创建期间,您将服务注入中间件,中间件处理影响服务的任何操作.

A further way I haven't tried, but seen used, is to use middleware in conjunction with Redux. You define your service object outside the application, or at least, higher than the redux store. During store creation, you inject the service into the middleware and the middleware handles any actions that affect the service.

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

In this way, I could inject my restful.js object into the middleware and replace my container methods with independent actions. I'd still need a container component to provide the actions to the form view layer, but connect() and mapDispatchToProps have me covered there.

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

The new v4 react-router-redux uses this method to impact the state of the history, for example.

//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)
  }
}

这篇关于在 React 应用程序中提供服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆