Услуги в ReactJS [дубликат]

50
задан Dennis Nerush 7 March 2016 в 23:53
поделиться

10 ответов

Первый ответ не отражает текущую парадигму Container vs Presenter .

Если вам нужно что-то сделать, например, проверить пароль, вы, вероятно, будете иметь функцию это делает. Вы передадите эту функцию вашему многоразовому представлению в качестве опоры.

Контейнеры

Итак, правильный способ сделать это - написать ValidatorContainer, который будет иметь эту функцию как свойство и обернуть в нее форму, передав правильные реквизиты в для ребенка. Когда дело доходит до вашего представления, ваш контейнер проверки валидатора обертывает ваше представление, и представление потребляет логику контейнеров.

В свойствах контейнера может быть выполнена проверка, но вы используете сторонний валидатор или любую простую службу проверки, вы можете использовать эту службу как свойство компонента контейнера и использовать ее в методы контейнера. Я сделал это для успокоительных компонентов, и он работает очень хорошо.

Провайдеры

Если вам нужна дополнительная конфигурация, вы можете использовать модель Provider / Consumer. Поставщик - это компонент высокого уровня, который помещается где-то рядом и под верхним объектом приложения (тот, который вы монтируете) и поставляет часть контекста или свойство, настроенное на верхнем уровне, в контекстный API. Затем я устанавливаю, чтобы элементы контейнера потребляли контекст.

Соотношения родительского / дочернего контекста не должны находиться рядом друг с другом, а только ребенок должен быть каким-то образом сгенерирован. Таким образом, хранилища Redux и функция React Router. Я использовал его для создания корневого успокоительного контекста для контейнеров для отдыха (если я не предоставляю свои собственные).

(примечание: контекстный 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
};

Middleware

Еще один способ, который я не пробовал, но видел используемый, - использовать промежуточное программное обеспечение в сочетании с Redux. Вы определяете свой сервисный объект вне приложения или, по крайней мере, выше, чем хранилище redux. Во время создания хранилища вы вводите услугу в промежуточное ПО, а промежуточное программное обеспечение обрабатывает любые действия, которые влияют на службу.

Таким образом, я мог бы вставить мой объект restful.js в промежуточное ПО и заменить мои методы контейнера независимыми действиями. Мне по-прежнему нужен компонент контейнера для обеспечения действий на уровне представления формы, но connect () и mapDispatchToProps меня покрыли.

Новый v4 response-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)
  }
}

20
ответ дан aphenine 5 September 2018 в 07:17
поделиться

Сервис не ограничивается угловым, даже в Angular2 +,

. Сервис - это просто набор вспомогательных функций ...

И существует множество способов их создания и повторного использования приложение ...

1) Они могут быть все разделенные функции, которые экспортируются из js-файла, как показано ниже:

export const firstFunction = () => {
   return "firstFunction";
}

export const secondFunction = () => {
   return "secondFunction";
}
//etc

2) Мы также можем использовать заводской метод например, с набором функций ... с ES6 это может быть класс, а не конструктор функции:

class myService {

  constructor() {
    this._data = null;
  }

  setMyService(data) {
    this._data = data;
  }

  getMyService() {
    return this._data;
  }

}

В этом случае вам нужно создать экземпляр с новым ключом ...

const myServiceInstance = new myService();

Также в этом случае каждый экземпляр имеет свою собственную жизнь, поэтому будьте осторожны, если вы хотите поделиться им, в этом случае вам нужно экспортировать только тот экземпляр, который вы хотите ...

3) Если ваша функция и utils не будут разделены, вы можете даже поместить их в компонент React, в этом случае, как функцию в вашем компоненте реакции ...

class Greeting extends React.Component {
  getName() {
    return "Alireza Dezfoolian";
  }

  render() {
    return <h1>Hello, {this.getName()}</h1>;
  }
}

4) Еще один способ, которым вы может обрабатывать вещи, может использовать Redux, это временный магазин для вас, поэтому, если вы его используете в своем приложении React lication, он может помочь вам с множеством функций setter setter, которые вы используете ... Это похоже на большой магазин, в котором хранятся следы ваших состояний, и вы можете делиться ими по своим компонентам, поэтому можете избавиться от многих проблем, возникающих при работе с геттерами, которые мы используем в услуги ...

Всегда полезно делать СУХОЙ код и не повторять то, что нужно использовать, чтобы сделать код многоразовым и читаемым, но не пытайтесь следовать угловым способам в приложении React, как указано в пункте 4, использование Redux может снизить потребность в услугах и ограничить их использование для некоторых вспомогательных вспомогательных функций, таких как item 1 ...

1
ответ дан Alireza 5 September 2018 в 07:17
поделиться

Я тоже из Angular и тестирую React, на данный момент один рекомендуемый способ (?), кажется, использует Компоненты высокого порядка :

Компонент более высокого порядка (HOC) является передовым методом в React для повторного использования компонентной логики. HOCs не являются частью React API, как таковой.

Предположим, что у вас есть input и textarea и как применять одну и ту же логику проверки:

const Input = (props) => (
  <input type="text"
    style={props.style}
    onChange={props.onChange} />
)
const TextArea = (props) => (
  <textarea rows="3"
    style={props.style}
    onChange={props.onChange} >
  </textarea>
)

Затем напишите HOC, который проверяет и стирает завернутый компонент:

function withValidator(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props)

      this.validateAndStyle = this.validateAndStyle.bind(this)
      this.state = {
        style: {}
      }
    }

    validateAndStyle(e) {
      const value = e.target.value
      const valid = value && value.length > 3 // shared logic here
      const style = valid ? {} : { border: '2px solid red' }
      console.log(value, valid)
      this.setState({
        style: style
      })
    }

    render() {
      return <WrappedComponent
        onChange={this.validateAndStyle}
        style={this.state.style}
        {...this.props} />
    }
  }
}

Теперь эти HOC имеют одно и то же поведение проверки:

const InputWithValidator = withValidator(Input)
const TextAreaWithValidator = withValidator(TextArea)

render((
  <div>
    <InputWithValidator />
    <TextAreaWithValidator />
  </div>
), document.getElementById('root'));

Я создал простой demo .

Редактировать: В другом демо используется реквизит для передачи массива функций, чтобы вы могли делиться логикой, состоящей из нескольких проверяющих функций через HOC s, например :

<InputWithValidator validators={[validator1,validator2]} />
<TextAreaWithValidator validators={[validator1,validator2]} />
2
ответ дан bob 5 September 2018 в 07:17
поделиться

В той же ситуации: Проделав несколько Угловых проектов и перейдя к Реагированию, не имея простого способа предоставления услуг через DI, кажется, что отсутствует кусок (особенности обслуживания в стороне).

Используя контекст и декораторы ES7, мы можем приблизиться:

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

Кажется, эти ребята сделали это еще дальше / в другом направлении:

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

Все еще чувствует, что работает против зерна. Повторите этот ответ через 6 месяцев после проведения крупного проекта React.

EDIT: Назад через 6 месяцев с некоторым опытом React. Рассмотрим природу логики:

  1. Связана ли она (только) с пользовательским интерфейсом? Переместить его в компонент (принятый ответ).
  2. Связано ли это (только) с управлением состоянием? Переместите его в thunk .
  3. Связано с обоими? Переместить в отдельный файл, потреблять в компоненте через селектор и в thunks.

Некоторые из них также доступны для HOCs для повторного использования, но для меня вышеупомянутое охватывает почти все варианты использования. Кроме того, рассмотрите масштабирование управления состоянием с помощью уток , чтобы держать проблемы отдельными и указывать на пользовательский интерфейс.

7
ответ дан corolla 5 September 2018 в 07:17
поделиться

Имейте в виду, что цель Реагента состоит в том, чтобы лучше сочетать вещи, которые логически должны быть связаны. Если вы разрабатываете сложный метод «проверки пароля», где его следует связывать?

Ну, вам нужно будет использовать его каждый раз, когда пользователю нужно ввести новый пароль. Это может быть на экране регистрации, экране «забытый пароль», экране администратора «Сбросить пароль для другого пользователя» и т. Д.

. Но в любом из этих случаев он всегда будет привязан к некоторым текстовое поле ввода. Таким образом, это должно быть связано.

Создайте очень маленький компонент React, который состоит исключительно из поля ввода и связанной логики проверки. Введите этот компонент во все формы, которые могут потребовать ввода пароля.

По сути, это тот же результат, что и для службы / фабрики для логики, но вы связываете его непосредственно со входом. Таким образом, вам теперь не нужно указывать эту функцию, где искать вход для проверки, поскольку он постоянно связан.

25
ответ дан gravityplanx 5 September 2018 в 07:17
поделиться

Я также пришел из области Angular.js, а службы и фабрики в React.js более просты.

Вы можете использовать простые функции или классы, стиль обратного вызова и событие Mobx, как и я:)

// Here we have Service class > dont forget that in JS class is Function
class HttpService {
  constructor() {
    this.data = "Hello data from HttpService";
    this.getData = this.getData.bind(this);
  }

  getData() {
    return this.data;
  }
}


// Making Instance of class > it's object now
const http = new HttpService();


// Here is React Class extended By React
class ReactApp extends React.Component {
  state = {
    data: ""
  };

  componentDidMount() {
    const data = http.getData();

    this.setState({
      data: data
    });
  }

  render() {
    return <div>{this.state.data}</div>;
  }
}

ReactDOM.render(<ReactApp />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  
  <div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

</body>
</html>

Вот простой пример:

7
ответ дан Juraj Sarissky 5 September 2018 в 07:17
поделиться

Мне нужна была какая-то логика форматирования для совместного использования несколькими компонентами, а также, как разработчик Angular, естественно, склонялся к службе.

Я разделил логику, поместив ее в отдельный файл

function format(input) {
    //convert input to output
    return output;
}

module.exports = {
    format: format
};

, а затем импортировал его как модуль

import formatter from '../services/formatter.service';

//then in component

    render() {

        return formatter.format(this.props.data);
    }
12
ответ дан Kildareflare 5 September 2018 в 07:17
поделиться

, или вы можете ввести наследование класса «http» в React Component

через объект реквизита.

  1. update:
    ReactDOM.render(<ReactApp data={app} />, document.getElementById('root'));
    
  2. Просто Изменить React Component ReactApp следующим образом:
    class ReactApp extends React.Component {
    
    state = {
    
        data: ''
    
    }
    
        render(){
    
        return (
            <div>
            {this.props.data.getData()}      
            </div>
    
        )
        }
    }
    
1
ответ дан Pang 5 September 2018 в 07:17
поделиться

Я нахожусь в той же самой загрузке, что и вы. В случае, о котором вы упоминаете, я бы использовал компонент пользовательского интерфейса проверки ввода как компонент React.

Я согласен, что сама реализация логики проверки должна (должна) не связываться. Поэтому я бы поместил его в отдельный JS-модуль.

То есть для логики, которая не должна быть связана, используйте JS-модуль / класс в отдельном файле и используйте require / import, чтобы отделить компонент от «услуга».

Это позволяет осуществлять инъекцию зависимостей и модульное тестирование этих двух независимо.

1
ответ дан sibidiba 5 September 2018 в 07:17
поделиться

Проблема становится чрезвычайно простой, когда вы понимаете, что угловая служба - это просто объект, который предоставляет набор контекстно-независимых методов. Это просто механизм Angular DI, который делает его более сложным. DI полезен, поскольку он заботится о создании и обслуживании экземпляров для вас, но вам это действительно не нужно.

Рассмотрим популярную библиотеку AJAX с именем axios (о которой вы, наверное, слышали):

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

Не работает ли она как служба? Он предоставляет набор методов, отвечающих за определенную логику и не зависящий от основного кода.

В вашем примере речь шла о создании изолированного набора методов для проверки ваших входов (например, проверка силы пароля). Некоторые предложили поместить эти методы в компоненты, которые для меня явно являются анти-шаблонами. Что делать, если валидация включает в себя создание и обработку обратных запросов XHR или выполнение сложных вычислений? Смешаете ли вы эту логику с обработчиками щелчков мыши и другими пользовательскими интерфейсами? Бред какой то. То же самое с подходом контейнера / HOC. Развертывание компонента только для добавления метода, который будет проверять, имеет ли значение цифру в нем? Давай.

Я бы просто создал новый файл с именем say '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.

Возможно, вам понадобится более сложная услуга, которая зависит от других сервисов. В этом случае ваш служебный файл может возвращать конструктор класса вместо статического объекта, чтобы вы могли создать экземпляр объекта самостоятельно в компоненте. Вы также можете рассмотреть возможность внедрения простого синглтона для обеспечения того, чтобы во всем приложении всегда использовался только один экземпляр объекта службы.

5
ответ дан Wojciech Majerski 5 September 2018 в 07:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: