Posiadanie usług w aplikacji React

176

Pochodzę ze świata kątowego, w którym mogłem wyodrębnić logikę do usługi / fabryki i skonsumować ją w moich kontrolerach.

Próbuję zrozumieć, jak mogę osiągnąć to samo w aplikacji React.

Powiedzmy, że mam komponent, który weryfikuje wprowadzone hasło użytkownika (jest to siła). Jego logika jest dość złożona, dlatego nie chcę zapisywać jej w komponencie, który sam jest.

Gdzie mam napisać tę logikę? W sklepie, jeśli używam topnika? Czy jest lepsza opcja?

Dennis Nerush
źródło
Możesz użyć pakietu i zobaczyć, jak to robią - npmjs.com/package/react-password-strength-meter
James111
11
Siła hasła to tylko przykład. Szukam bardziej ogólnej najlepszej praktyki
Dennis Nerush
Być może będziesz musiał to zrobić po stronie serwera?
James111,
2
Nie. Tylko logika po stronie klienta, która nie powinna znajdować się bezpośrednio w komponencie. Narzędzie do sprawdzania siły hasła to tylko przykład
Dennis Nerush
4
Jeśli masz wiele takich funkcji, możesz przechowywać je w pliku pomocniczym i po prostu wymagać ich w pliku komponentów do użycia. Jeśli jest to pojedyncza funkcja, która jest istotna wyłącznie dla tego komponentu, prawdopodobnie powinna tam istnieć bez względu na złożoność.
Jesse Kernaghan

Odpowiedzi:

60

Pierwsza odpowiedź nie odzwierciedla obecnego paradygmatu kontenera i prezentera .

Jeśli musisz coś zrobić, na przykład zweryfikować hasło, prawdopodobnie masz funkcję, która to robi. Przekazałbyś tę funkcję do widoku wielokrotnego użytku jako rekwizyt.

Pojemniki

Tak więc poprawnym sposobem na zrobienie tego jest napisanie ValidatorContainer, który będzie miał tę funkcję jako właściwość i zawinięcie w nią formularza, przekazując odpowiednie rekwizyty dziecku. Jeśli chodzi o widok, kontener walidatora otacza widok, a widok zużywa logikę kontenerów.

Walidację można przeprowadzić we właściwościach kontenera, ale jeśli używasz walidatora innej firmy lub dowolnej prostej usługi walidacji, możesz użyć usługi jako właściwości komponentu kontenera i użyć jej w metodach kontenera. Zrobiłem to dla spokojnych komponentów i działa to bardzo dobrze.

Dostawcy

Jeśli wymagana jest nieco większa konfiguracja, możesz użyć modelu dostawcy / konsumenta. Dostawca to komponent wysokiego poziomu, który znajduje się w pobliżu i poniżej najwyższego obiektu aplikacji (tego, który montujesz) i dostarcza część samego siebie lub właściwość skonfigurowaną w górnej warstwie do kontekstowego interfejsu API. Następnie ustawiam elementy kontenera, aby zużywały kontekst.

Relacje kontekstu rodzic / dziecko nie muszą być blisko siebie, po prostu dziecko musi w jakiś sposób zejść. W ten sposób Redux przechowuje i React Router. Użyłem go, aby zapewnić korzeń kontekstu odpoczynku dla moich kontenerów odpoczynku (jeśli nie podam własnego).

(uwaga: kontekstowy interfejs API jest oznaczony jako eksperymentalny w dokumentacji, ale nie sądzę, aby był już dłużej, biorąc pod uwagę, co go używa).

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

Oprogramowanie pośredniczące

Kolejnym sposobem, którego nie próbowałem, ale widziałem, że jest używany, jest użycie oprogramowania pośredniczącego w połączeniu z Redux. Obiekt usługi definiujesz poza aplikacją lub przynajmniej wyżej niż sklep redux. Podczas tworzenia sklepu wstrzykujesz usługę do oprogramowania pośredniego, a oprogramowanie pośredniczące obsługuje wszelkie akcje, które mają wpływ na usługę.

W ten sposób mogłem wstrzyknąć obiekt restful.js do oprogramowania pośredniego i zastąpić metody kontenera niezależnymi akcjami. Nadal potrzebowałbym komponentu kontenera, aby dostarczyć akcje do warstwy widoku formularza, ale connect () i mapDispatchToProps mają mnie tam omówione.

Nowa wersja react-router-redux wykorzystuje tę metodę na przykład do wpływania na stan historii.

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

aphenina
źródło
świetna odpowiedź kolego, powstrzymałeś mnie od robienia rzeczy bezmyślnych 8) KUDOS !!
csomakk
jakie jest zastosowanie na przykład kontenera?
sensei,
Nie opowiadam się za tym, ale jeśli chcesz przejść przez ścieżkę lokalizatora usług (coś podobnego do Angulara), możesz dodać pewnego rodzaju dostawcę „wtryskiwacza / kontenera”, od którego rozwiązujesz usługi (po wcześniejszym zarejestrowaniu).
eddiewould
Z pomocą przychodzą haki React. Dzięki hookom możesz napisać logikę wielokrotnego użytku bez pisania klasy. actjs.org/docs/…
Raja Malik
102

Problem staje się niezwykle prosty, gdy zdasz sobie sprawę, że usługa Angular to tylko obiekt, który dostarcza zestaw metod niezależnych od kontekstu. To tylko mechanizm Angular DI sprawia, że ​​wygląda bardziej skomplikowanie. DI jest przydatny, ponieważ zajmuje się tworzeniem i utrzymywaniem instancji, ale tak naprawdę go nie potrzebujesz.

Rozważ popularną bibliotekę AJAX o nazwie axios (o której prawdopodobnie słyszałeś):

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

Czy nie zachowuje się jak usługa? Zapewnia zestaw metod odpowiedzialnych za określoną logikę i jest niezależny od głównego kodu.

Twój przykład dotyczył stworzenia izolowanego zestawu metod sprawdzania poprawności danych wejściowych (np. Sprawdzania siły hasła). Niektórzy sugerowali umieszczenie tych metod w komponentach, co dla mnie jest ewidentnie anty-wzorcem. Co jeśli walidacja obejmuje wykonywanie i przetwarzanie wywołań XHR backendu lub wykonywanie złożonych obliczeń? Czy mógłbyś połączyć tę logikę z funkcjami obsługi kliknięć myszą i innymi elementami interfejsu użytkownika? Nonsens. To samo z podejściem kontenerowym / HOC. Pakowanie komponentu tylko po to, aby dodać metodę, która sprawdzi, czy wartość zawiera cyfrę? Daj spokój.

Po prostu utworzyłbym nowy plik o nazwie „ValidationService.js” i zorganizowałbym go w następujący sposób:

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

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

export default ValidationService;

Następnie w swoim komponencie:

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

...

//inside the component
yourInputChangeHandler(event) {

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

Korzystaj z tej usługi z dowolnego miejsca. Jeśli zasady sprawdzania poprawności ulegną zmianie, należy skupić się tylko na pliku ValidationService.js.

Możesz potrzebować bardziej skomplikowanej usługi, która zależy od innych usług. W takim przypadku plik usługi może zwrócić konstruktor klasy zamiast obiektu statycznego, dzięki czemu można samodzielnie utworzyć instancję obiektu w komponencie. Można również rozważyć zaimplementowanie prostego singletona, aby upewnić się, że w całej aplikacji jest zawsze używane tylko jedno wystąpienie obiektu usługi.

Wojtek Majerski
źródło
3
W ten sposób też bym to zrobił. Jestem dość zaskoczony, że ta odpowiedź ma tak mało głosów, ponieważ wydaje się, że jest to droga najmniej tarcia. Jeśli twoja usługa zależy od innych usług, to znowu będzie importować te inne usługi za pośrednictwem ich modułów. Co więcej, moduły są z definicji singletonami, więc właściwie nie jest potrzebna żadna dodatkowa praca, aby "zaimplementować to jako prosty singleton" - otrzymujesz to zachowanie za darmo :)
Mickey Puri
6
+1 - Dobra odpowiedź, jeśli korzystasz tylko z usług, które zapewniają funkcje. Jednak usługa Angular to klasy, które są definiowane raz, zapewniając w ten sposób więcej funkcji niż tylko dostarczanie funkcji. Na przykład obiekty można buforować jako parametr klasy usług.
Nino Filiu
6
To powinna być prawdziwa odpowiedź, a nie zbyt skomplikowana odpowiedź powyżej
user1807334
1
To dobra odpowiedź, ale nie jest „reaktywna”. DOM nie aktualizuje się przy zmianach zmiennych w usłudze.
Defacto
9
A co z zastrzykiem zależności? Usługa jest niemożliwa do podrobienia w komponencie, chyba że w jakiś sposób ją wstrzykniesz. Być może posiadanie globalnego obiektu najwyższego poziomu „kontenera”, w którym każda usługa jest polem, pozwoli obejść ten problem. Następnie w testach możesz zastąpić pola kontenerów makietami dla usług, które chcesz symulować.
menehune
34

Potrzebowałem pewnej logiki formatowania, która byłaby współdzielona przez wiele komponentów, a jako programista Angular również naturalnie skłaniałem się ku usłudze.

Podzieliłem się logiką, umieszczając ją w osobnym pliku

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

module.exports = {
    format: format
};

a następnie zaimportować go jako moduł

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

//then in component

    render() {

        return formatter.format(this.props.data);
    }
Kildareflare
źródło
8
Jest to dobry pomysł, o czym nawet wspomniano w dokumencie React: Reactjs.org/docs/composition-vs-inheritance.html Jeśli chcesz ponownie wykorzystać funkcje niezwiązane z interfejsem użytkownika między komponentami, sugerujemy wyodrębnienie ich do oddzielnego modułu JavaScript. Komponenty mogą ją importować i używać tej funkcji, obiektu lub klasy bez jej rozszerzania.
user3426603
To właściwie jedyna sensowna odpowiedź.
Artem Novikov
33

Pamiętaj, że celem Reacta jest lepsze połączenie rzeczy, które logicznie powinny być połączone. Jeśli projektujesz skomplikowaną metodę „walidacji hasła”, gdzie powinna być połączona?

Będziesz musiał go używać za każdym razem, gdy użytkownik będzie musiał wprowadzić nowe hasło. Może to być ekran rejestracji, ekran „zapomniałem hasła”, ekran administratora „resetowanie hasła innego użytkownika” itp.

Ale w każdym z tych przypadków zawsze będzie on powiązany z jakimś polem wprowadzania tekstu. Więc to jest miejsce, w którym powinno być połączone.

Stwórz bardzo mały komponent React, który składa się wyłącznie z pola wejściowego i powiązanej logiki walidacji. Wprowadź ten składnik we wszystkich formularzach, które mogą wymagać wprowadzenia hasła.

Zasadniczo jest to ten sam wynik, co posiadanie usługi / fabryki logiki, ale łączysz ją bezpośrednio z wejściem. Więc teraz nigdy nie musisz mówić tej funkcji, gdzie ma szukać swoich danych wejściowych walidacji, ponieważ jest ona trwale związana.

Jake Roby
źródło
11
Jaka jest zła praktyka łączenia logiki i interfejsu użytkownika. Żeby zmienić logikę będę musiał dotknąć komponentu
Dennis Nerush
14
Reaguj zasadniczo na wyzwania, które podejmujesz. Stanowi ostry kontrast w stosunku do tradycyjnej architektury MVC. Ten film całkiem nieźle wyjaśnia, dlaczego tak jest (odpowiednia sekcja zaczyna się około 2 minut).
Jake Roby
8
Co się stanie, jeśli ta sama logika walidacji będzie musiała zostać zastosowana również do elementu obszaru tekstowego? Logika nadal musi zostać wyodrębniona do udostępnionego pliku. Wydaje mi się, że po wyjęciu z pudełka nie ma żadnego odpowiednika z biblioteki reagującej. Usługa Angular to narzędzia iniekcyjne, a platforma Angular jest zbudowana na podstawie wzorca projektowania iniekcji zależności, który umożliwia wystąpienia zależności zarządzanych przez Angular. Gdy usługa jest wstrzykiwana, zwykle w podanym zakresie znajduje się singleton, aby mieć tę samą usługę w Reakcie, do aplikacji należy wprowadzić bibliotekę DI innej firmy.
Downhillski
15
@gravityplanx Lubię używać React. To nie jest wzór kątowy, to jest wzorzec projektowy oprogramowania. Lubię mieć otwarty umysł, pożyczając rzeczy, które lubię, z innych dobrych stron.
Downhillski
1
Moduły @MickeyPuri ES6 to nie to samo co Dependency Injection.
Spock
12

Pochodzę też z obszaru Angular.js, a usługi i fabryki w React.js są prostsze.

Możesz używać prostych funkcji lub klas, stylu wywołania zwrotnego i zdarzenia Mobx jak ja :)

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

Oto prosty przykład:

Juraj
źródło
React.js to biblioteka UI do renderowania i organizowania komponentów UI. Jeśli chodzi o usługi, które mogą nam pomóc w dodawaniu dodatkowych funkcjonalności, to powinniśmy tworzyć zbiory funkcji, obiektów funkcjonalnych lub klas. Uważam, że klasy są bardzo przydatne, ale wiem, że gram także stylem funkcjonalnym, który może być również użyty do tworzenia pomocników do dodawania zaawansowanych funkcji, które są poza zakresem Reac.js.
Juraj
Właśnie to zaimplementowałem. Sposób, w jaki stworzyłeś z tego klasę i wyeksportowałeś, jest dość elegancki.
GavinBelson,
10

Ta sama sytuacja: po wykonaniu wielu projektów Angular i przejściu do React, brak prostego sposobu świadczenia usług za pośrednictwem DI wydaje się brakującym elementem (poza szczegółami usługi).

Korzystając z dekoratorów Context i ES7, możemy zbliżyć się:

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

Wygląda na to, że ci goście poszli o krok dalej / w innym kierunku:

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

Nadal ma się ochotę pracować pod włosem. Wrócę do tej odpowiedzi za 6 miesięcy po podjęciu dużego projektu React.

EDYCJA: Wróć 6 miesięcy później z większym doświadczeniem w React. Rozważ naturę logiki:

  1. Czy jest powiązany (tylko) z interfejsem użytkownika? Przenieś go do komponentu (zaakceptowana odpowiedź).
  2. Czy jest powiązany (tylko) z zarządzaniem państwem? Przenieś to do huku .
  3. Związany z oboma? Przejdź do oddzielnego pliku, zużyj w komponencie przez selektor i w złączach.

Niektórzy sięgają również po HOC-y do ponownego wykorzystania, ale dla mnie powyższe obejmuje prawie wszystkie przypadki użycia. Rozważ również skalowanie zarządzania stanem za pomocą kaczek, aby oddzielić obawy i skoncentrować się na interfejsie użytkownika.

korona
źródło
Imho myślę, że jest to prosta droga do świadczenia usług thru DI, przy użyciu systemu ES6 Module
Mickey Puri
1
@MickeyPuri, moduł ES6 DI nie obejmowałby hierarchicznej natury Angular DI, tj. rodzice (w DOM) tworzą wystąpienia i przesłaniają usługi dostarczane do komponentów podrzędnych. Imho ES6 moduł DI porównuje się bliżej do systemów DI zaplecza, takich jak Ninject i Structuremap, siedząc z dala od hierarchii komponentów DOM, zamiast być na niej opartym. Ale chciałbym usłyszeć, co o tym myślisz.
corolla
6

Jestem również z Angulara i wypróbowuję Reacta, jak na razie wydaje się, że jednym zalecanym (?) Sposobem jest używanie komponentów wysokiego zamówienia :

Komponent wyższego rzędu (HOC) to zaawansowana technika w Reakcie do ponownego wykorzystania logiki komponentów. HOC nie są jako takie częścią interfejsu API React. Są wzorem, który wyłania się z kompozycyjnej natury Reacta.

Powiedzmy, że masz inputi textareai chcesz zastosować tę samą logikę walidacji:

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

Następnie napisz HOC, który sprawdza poprawność i stylizuje opakowany komponent:

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

Teraz te HOC mają to samo zachowanie podczas walidacji:

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

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

Stworzyłem proste demo .

Edycja : Kolejne demo używa właściwości do przekazywania tablicy funkcji, dzięki czemu możesz udostępniać logikę złożoną z wielu funkcji walidacyjnych w różnych HOCs, takich jak:

<InputWithValidator validators={[validator1,validator2]} />
<TextAreaWithValidator validators={[validator1,validator2]} />

Edit2 : React 16.8+ zapewnia nową funkcję, Hook , kolejny fajny sposób na dzielenie się logiką.

const Input = (props) => {
  const inputValidation = useInputValidation()

  return (
    <input type="text"
    {...inputValidation} />
  )
}

function useInputValidation() {
  const [value, setValue] = useState('')
  const [style, setStyle] = useState({})

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

  return {
    value,
    style,
    onChange: handleChange
  }
}

https://stackblitz.com/edit/react-shared-validation-logic-using-hook?file=index.js

pion
źródło
Dziękuję Ci. Naprawdę nauczyłem się z tego rozwiązania. A jeśli potrzebuję więcej niż jednego walidatora. Na przykład oprócz walidatora 3-literowego, co jeśli chcę mieć inny walidator, który upewnia się, że żadne liczby nie są wprowadzane. Czy moglibyśmy skomponować walidatory?
Youssef Sherif
1
@YoussefSherif Możesz przygotować wiele funkcji walidujących i przekazać je jako rekwizyty HOC, zobacz moją edycję dla innego demo.
bob
więc HOC jest w zasadzie składnikiem pojemnika?
sensei
Tak, z dokumentu React: „Zauważ, że KWR nie modyfikuje komponentu wejściowego, ani nie używa dziedziczenia do kopiowania swojego zachowania. Raczej KWR komponuje oryginalny komponent, opakowując go w komponent kontenera. KWR jest czystym działa bez skutków ubocznych. "
bob
1
Wymaganiem było wstrzyknięcie logiki, nie widzę, dlaczego potrzebujemy do tego HOC. Chociaż możesz to zrobić za pomocą HOC, wydaje się to zbyt skomplikowane. Moje rozumienie HOC jest wtedy, gdy istnieje również dodatkowy stan, który należy dodać i nim zarządzać, tj. Nie jest to czysta logika (co miało miejsce w tym przypadku).
Mickey Puri
4

Usługa nie ogranicza się do Angulara , nawet w Angular2 + ,

Usługa to po prostu zbiór funkcji pomocniczych ...

Istnieje wiele sposobów ich tworzenia i ponownego wykorzystywania w całej aplikacji ...

1) Mogą to być wszystkie oddzielne funkcje, które są eksportowane z pliku js, podobnie jak poniżej:

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

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

2) Możemy również użyć metody fabrycznej, takiej jak zbiór funkcji ... w ES6 może to być klasa, a nie konstruktor funkcji:

class myService {

  constructor() {
    this._data = null;
  }

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

  getMyService() {
    return this._data;
  }

}

W takim przypadku musisz utworzyć instancję z nowym kluczem ...

const myServiceInstance = new myService();

Również w tym przypadku każda instancja ma swoje własne życie, więc bądź ostrożny, jeśli chcesz ją udostępnić, w takim przypadku powinieneś wyeksportować tylko tę instancję, którą chcesz ...

3) Jeśli twoja funkcja i narzędzia nie będą udostępniane, możesz nawet umieścić je w komponencie React, w tym przypadku, tak samo jak funkcje w komponencie React ...

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

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

4) Innym sposobem, w jaki możesz sobie z tym poradzić, może być użycie Redux , jest to tymczasowy magazyn dla ciebie, więc jeśli masz go w swojej aplikacji React , może ci pomóc z wieloma funkcjami getter setter których używasz ... To jest jak duży sklep które śledzą twoje stany i mogą udostępniać je w twoich komponentach, dzięki czemu mogą pozbyć się wielu problemów związanych z elementami ustawiającymi getter, których używamy w usługach ...

Zawsze dobrze jest zrobić kod DRY i nie powtarzać tego, co jest potrzebne, aby kod był wielokrotnego użytku i czytelny, ale nie próbuj podążać za ścieżkami Angulara w aplikacji React , jak wspomniano w punkcie 4, użycie Redux może zmniejszyć potrzebę usług i ograniczasz używanie ich do niektórych funkcji pomocniczych wielokrotnego użytku, takich jak pozycja 1 ...

Alireza
źródło
Jasne, możesz go znaleźć na mojej osobistej stronie internetowej, do której link znajduje się na moim profilu ...
Alireza
„Nie podążaj za ścieżkami Angulara w React”… ahem Angular promuje użycie Redux i przesyłanie strumieniowe ze sklepu do komponentów prezentacji za pomocą Observables i zarządzania stanem podobnego do Redux, takiego jak RxJS / Store. .. czy miałeś na myśli AngularJS? Bo to inna sprawa
Spock
1

Jestem w takim samym bucie jak ty. W przypadku, o którym wspomniałeś, zaimplementowałbym komponent UI walidacji danych wejściowych jako komponent React.

Zgadzam się, że implementacja samej logiki walidacji nie powinna (nie może) być łączona. Dlatego umieściłbym go w osobnym module JS.

Oznacza to, że dla logiki, która nie powinna być łączona, użyj modułu / klasy JS w oddzielnym pliku i użyj funkcji require / import w celu odłączenia komponentu od „usługi”.

Pozwala to na niezależne wstrzykiwanie i testowanie jednostkowe tych dwóch niezależnie.

sibidiba
źródło
1

lub możesz wstrzyknąć dziedziczenie klas „http” do komponentu React

za pośrednictwem obiektu props.

  1. aktualizacja :

    ReactDOM.render(<ReactApp data={app} />, document.getElementById('root'));
  2. Po prostu edytuj React Component ReactApp w ten sposób:

    class ReactApp extends React.Component {
    
    state = {
    
        data: ''
    
    }
    
        render(){
    
        return (
            <div>
            {this.props.data.getData()}      
            </div>
    
        )
        }
    }
Juraj
źródło
0

Cóż, najczęściej używanym wzorcem logiki wielokrotnego użytku, z jakim się spotkałem, jest napisanie hooka lub utworzenie pliku utils. To zależy od tego, co chcesz osiągnąć.

hooks/useForm.js

Na przykład, jeśli chcesz sprawdzić poprawność danych formularza, utworzyłbym niestandardowy punkt zaczepienia o nazwie useForm.js i udostępniłby mu dane formularza, a w zamian zwróciłbym mi obiekt zawierający dwie rzeczy:

Object: {
    value,
    error,
}

Z pewnością możesz zwrócić z niego więcej rzeczy w miarę postępów.

utils/URL.js

Innym przykładem może być wyodrębnienie niektórych informacji z adresu URL, a następnie utworzę dla niego plik utils zawierający funkcję i zaimportuj go w razie potrzeby:

 export function getURLParam(p) {
...
}
Muhammad Shahryar
źródło