Dienste in der React-Anwendung haben

176

Ich komme aus der eckigen Welt, in der ich Logik zu einem Service / einer Fabrik extrahieren und sie in meinen Controllern verbrauchen könnte.

Ich versuche zu verstehen, wie ich dasselbe in einer React-Anwendung erreichen kann.

Angenommen, ich habe eine Komponente, die die Passworteingabe des Benutzers überprüft (deren Stärke). Die Logik ist ziemlich komplex, daher möchte ich sie nicht in die Komponente selbst schreiben.

Wo soll ich diese Logik schreiben? In einem Geschäft, wenn ich Flussmittel verwende? Oder gibt es eine bessere Option?

Dennis Nerush
quelle
Sie könnten ein Paket verwenden und sehen, wie sie es tun - npmjs.com/package/react-password-strength-meter
James111
11
Die Passwortstärke ist nur ein Beispiel. Ich suche nach einer allgemeineren Best Practice
Dennis Nerush
Möglicherweise müssen Sie es serverseitig tun?
James111
2
Nein. Nur clientseitige Logik, die sich nicht direkt in der Komponente befinden sollte. Die Passwortstärkeprüfung ist nur ein Beispiel
Dennis Nerush
4
Wenn Sie über viele solcher Funktionen verfügen, können Sie diese in einer Hilfsdatei speichern und zur Verwendung in Ihrer Komponentendatei benötigen. Wenn es sich um eine einzelne Funktion handelt, die nur für diese Komponente relevant ist, sollte sie unabhängig von der Komplexität wahrscheinlich dort leben.
Jesse Kernaghan

Antworten:

60

Die erste Antwort spiegelt nicht das aktuelle Paradigma von Container vs Presenter wider .

Wenn Sie etwas tun müssen, z. B. ein Passwort validieren, haben Sie wahrscheinlich eine Funktion, die dies tut. Sie würden diese Funktion an Ihre wiederverwendbare Ansicht als Requisite übergeben.

Behälter

Der richtige Weg, dies zu tun, besteht darin, einen ValidatorContainer zu schreiben, der diese Funktion als Eigenschaft hat, und das Formular darin zu verpacken und die richtigen Requisiten an das Kind zu übergeben. Wenn es um Ihre Ansicht geht, schließt Ihr Validator-Container Ihre Ansicht ein und die Ansicht verbraucht die Container-Logik.

Die Validierung kann in den Eigenschaften des Containers erfolgen. Wenn Sie jedoch einen Validator eines Drittanbieters oder einen einfachen Validierungsdienst verwenden, können Sie den Dienst als Eigenschaft der Containerkomponente verwenden und in den Methoden des Containers verwenden. Ich habe dies für erholsame Komponenten getan und es funktioniert sehr gut.

Anbieter

Wenn etwas mehr Konfiguration erforderlich ist, können Sie ein Provider / Consumer-Modell verwenden. Ein Anbieter ist eine übergeordnete Komponente, die sich in der Nähe und unterhalb des obersten Anwendungsobjekts (das von Ihnen bereitgestellten) befindet und der Kontext-API einen Teil von sich selbst oder eine in der obersten Ebene konfigurierte Eigenschaft bereitstellt. Ich setze dann meine Containerelemente so, dass sie den Kontext verbrauchen.

Die Eltern-Kind-Kontextbeziehungen müssen nicht nahe beieinander liegen, nur das Kind muss auf irgendeine Weise abstammen. Redux-Speicher und der React Router funktionieren auf diese Weise. Ich habe es verwendet, um einen Root-Restful-Kontext für meine Rest-Container bereitzustellen (wenn ich keinen eigenen bereitstelle).

(Hinweis: Die Kontext-API ist in den Dokumenten als experimentell markiert, aber ich glaube nicht, dass dies mehr der Fall ist, wenn man bedenkt, was sie verwendet.)

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

Ein weiterer Weg, den ich nicht ausprobiert, aber als gebraucht angesehen habe, ist die Verwendung von Middleware in Verbindung mit Redux. Sie definieren Ihr Serviceobjekt außerhalb der Anwendung oder zumindest höher als der Redux-Speicher. Während der Filialerstellung fügen Sie den Dienst in die Middleware ein, und die Middleware verarbeitet alle Aktionen, die sich auf den Dienst auswirken.

Auf diese Weise konnte ich mein restful.js-Objekt in die Middleware einfügen und meine Containermethoden durch unabhängige Aktionen ersetzen. Ich würde immer noch eine Containerkomponente benötigen, um die Aktionen für die Formularansichtsebene bereitzustellen, aber connect () und mapDispatchToProps haben mich dort behandelt.

Der neue v4-React-Router-Redux verwendet diese Methode beispielsweise, um den Status des Verlaufs zu beeinflussen.

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

Aphenin
quelle
tolle Antwort Kumpel, du hast mich davon abgehalten, hirnlose Sachen zu machen 8) KUDOS !!
Csomakk
Was ist die Verwendung für Container Beispiel?
Sensei
Ich befürworte es nicht, aber wenn Sie den Service Locator-Pfad (ähnlich wie Angular) einschlagen möchten, können Sie eine Art "Injektor / Container" -Anbieter hinzufügen, von dem Sie Services auflösen (nachdem Sie sie zuvor registriert haben).
Eddiewould
Reaktionshaken kommen zur Rettung. Mit Hooks können Sie wiederverwendbare Logik schreiben, ohne eine Klasse zu schreiben. reactjs.org/docs/…
Raja Malik
101

Das Problem wird extrem einfach, wenn Sie feststellen, dass ein Angular-Dienst nur ein Objekt ist, das eine Reihe kontextunabhängiger Methoden bereitstellt. Es ist nur der Angular DI-Mechanismus, der es komplizierter aussehen lässt. Der DI ist nützlich, da er sich um das Erstellen und Verwalten von Instanzen für Sie kümmert, diese aber nicht wirklich benötigt.

Stellen Sie sich eine beliebte AJAX-Bibliothek mit dem Namen axios vor (von der Sie wahrscheinlich schon gehört haben):

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

Benimmt es sich nicht als Dienstleistung? Es bietet eine Reihe von Methoden, die für eine bestimmte Logik verantwortlich sind, und ist unabhängig vom Hauptcode.

In Ihrem Beispielfall ging es darum, einen isolierten Satz von Methoden zum Überprüfen Ihrer Eingaben zu erstellen (z. B. Überprüfen der Kennwortstärke). Einige schlugen vor, diese Methoden in die Komponenten zu integrieren, was für mich eindeutig ein Anti-Muster ist. Was ist, wenn bei der Validierung XHR-Backend-Aufrufe durchgeführt und verarbeitet oder komplexe Berechnungen durchgeführt werden? Würden Sie diese Logik mit Mausklick-Handlern und anderen UI-spezifischen Dingen mischen? Unsinn. Gleiches gilt für den Container / HOC-Ansatz. Umschließen Sie Ihre Komponente nur, um eine Methode hinzuzufügen, mit der überprüft wird, ob der Wert eine Ziffer enthält? Komm schon.

Ich würde einfach eine neue Datei mit dem Namen "ValidationService.js" erstellen und sie wie folgt organisieren:

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

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

export default ValidationService;

Dann in Ihrer Komponente:

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

...

//inside the component
yourInputChangeHandler(event) {

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

Nutzen Sie diesen Service von jedem beliebigen Ort aus. Wenn sich die Validierungsregeln ändern, müssen Sie sich nur auf die Datei ValidationService.js konzentrieren.

Möglicherweise benötigen Sie einen komplizierteren Dienst, der von anderen Diensten abhängt. In diesem Fall gibt Ihre Servicedatei möglicherweise einen Klassenkonstruktor anstelle eines statischen Objekts zurück, sodass Sie selbst eine Instanz des Objekts in der Komponente erstellen können. Sie können auch ein einfaches Singleton implementieren, um sicherzustellen, dass in der gesamten Anwendung immer nur eine Instanz des Serviceobjekts verwendet wird.

Wojtek Majerski
quelle
3
So würde ich es auch machen. Ich bin ziemlich überrascht, dass diese Antwort so wenige Stimmen hat, da dies der Weg mit der geringsten Reibung ist. Wenn Ihr Dienst von anderen Diensten abhängt, werden diese anderen Dienste wiederum über ihre Module importiert. Darüber hinaus sind Module per Definition Singletons, so dass eigentlich keine weitere Arbeit erforderlich ist, um "es als einfaches Singleton zu implementieren" - Sie erhalten dieses Verhalten kostenlos :)
Mickey Puri
6
+1 - Gute Antwort, wenn Sie nur Dienste verwenden, die Funktionen bereitstellen. Jedoch , Angular Dienst sind Klassen , die einmal definiert sind, also mehr Funktionen als nur die Bereitstellung Funktionen. Sie können Objekte beispielsweise als Serviceklassenparameter zwischenspeichern.
Nino Filiu
6
Dies sollte die eigentliche Antwort sein und nicht die
überkomplizierte
1
Dies ist eine gute Antwort, außer es ist nicht "reaktiv". Das DOM wird bei Variablenänderungen innerhalb des Dienstes nicht aktualisiert.
Defacto
9
Was ist mit der Abhängigkeitsinjektion? Es ist unmöglich, den Service in Ihrer Komponente zu verspotten, es sei denn, Sie injizieren ihn irgendwie. Vielleicht würde ein globales "Container" -Objekt der obersten Ebene, das jeden Dienst als Feld hat, dies umgehen. In Ihren Tests können Sie dann die Containerfelder mit Mocks für die Dienste überschreiben, die Sie verspotten möchten.
Menehune23
34

Ich brauchte eine Formatierungslogik, die von mehreren Komponenten gemeinsam genutzt werden konnte, und als Angular-Entwickler neigte ich natürlich auch zu einem Dienst.

Ich teilte die Logik, indem ich sie in eine separate Datei legte

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

module.exports = {
    format: format
};

und importierte es dann als Modul

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

//then in component

    render() {

        return formatter.format(this.props.data);
    }
Kildareflare
quelle
8
Dies ist eine gute Idee, wie bereits im React-Dokument erwähnt: reactjs.org/docs/composition-vs-inheritance.html Wenn Sie Nicht-UI-Funktionen zwischen Komponenten wiederverwenden möchten, empfehlen wir, sie in ein separates JavaScript-Modul zu extrahieren. Die Komponenten können es importieren und diese Funktion, dieses Objekt oder eine Klasse verwenden, ohne es zu erweitern.
user3426603
Das ist eigentlich die einzige sinnvolle Antwort.
Artem Novikov
33

Denken Sie daran, dass der Zweck von React darin besteht, Dinge besser zu koppeln, die logisch gekoppelt werden sollten. Wenn Sie eine komplizierte "Passwort validieren" -Methode entwerfen, wo sollte sie gekoppelt werden?

Nun, Sie müssen es jedes Mal verwenden, wenn der Benutzer ein neues Passwort eingeben muss. Dies kann auf dem Registrierungsbildschirm, einem Bildschirm "Passwort vergessen", einem Administratorbildschirm "Passwort für einen anderen Benutzer zurücksetzen" usw. angezeigt werden.

In jedem dieser Fälle ist es jedoch immer an ein Texteingabefeld gebunden. Dort sollte es also gekoppelt werden.

Erstellen Sie eine sehr kleine React-Komponente, die ausschließlich aus einem Eingabefeld und der zugehörigen Validierungslogik besteht. Geben Sie diese Komponente in alle Formulare ein, für die möglicherweise eine Kennworteingabe erforderlich ist.

Es ist im Wesentlichen das gleiche Ergebnis wie ein Service / eine Factory für die Logik, aber Sie koppeln sie direkt an den Eingang. Sie müssen dieser Funktion jetzt nie mehr mitteilen, wo nach der Validierungseingabe gesucht werden soll, da sie permanent miteinander verbunden ist.

Jake Roby
quelle
11
Was es eine schlechte Praxis ist, Logik und Benutzeroberfläche zu koppeln. Um die Logik zu ändern, muss ich die Komponente berühren
Dennis Nerush
14
Reagieren stellt diese Annahme, die Sie machen, grundlegend in Frage. Es steht in starkem Kontrast zur traditionellen MVC-Architektur. In diesem Video wird ziemlich gut erklärt, warum das so ist (der relevante Abschnitt beginnt in ungefähr 2 Minuten).
Jake Roby
8
Was ist, wenn dieselbe Validierungslogik auch auf ein Textbereichselement angewendet werden muss? Die Logik muss noch in eine gemeinsam genutzte Datei extrahiert werden. Ich denke nicht, dass es eine Äquivalenz von der Reaktionsbibliothek gibt. Angular Service sind injizierbare Elemente, und das Angular-Framework basiert auf dem Entwurfsmuster für die Abhängigkeitsinjektion, das die Instanzen der von Angular verwalteten Abhängigkeiten ermöglicht. Wenn ein Dienst injiziert wird, befindet sich normalerweise ein Singleton im bereitgestellten Bereich. Um denselben Dienst in React zu haben, muss eine DI-Bibliothek eines Drittanbieters in die Anwendung eingeführt werden.
Downhillski
15
@gravityplanx Ich benutze gerne React. Dies ist kein Winkelmuster, sondern ein Software-Entwurfsmuster. Ich mag es, meine Gedanken zu öffnen, während ich Dinge aus anderen guten Teilen leihe, die ich mag.
Downhillski
1
@ MickeyPuri ES6-Module sind nicht mit Dependency Injection identisch.
Spock
12

Ich kam auch aus dem Bereich Angular.js und die Dienstleistungen und Fabriken in React.js sind einfacher.

Sie können einfache Funktionen oder Klassen, Rückrufstil und Ereignis Mobx wie ich verwenden :)

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

Hier ist ein einfaches Beispiel:

Juraj
quelle
React.js ist eine UI-Bibliothek zum Rendern und Organisieren von UI-Komponenten. Wenn es um Services geht, mit denen wir zusätzliche Funktionen hinzufügen können, sollten wir Sammlungen von Funktionen, Funktionsobjekten oder Klassen erstellen. Ich fand Klassen sehr nützlich, weiß aber, dass ich auch mit funktionalem Stil spiele, der auch zum Erstellen von Hilfsprogrammen zum Hinzufügen von vorteilhaften Funktionen verwendet werden kann, die außerhalb des Bereichs von Reac.js liegen.
Juraj
Gerade implementiert. Die Art und Weise, wie Sie es zu einer Klasse gemacht und exportiert haben, ist ziemlich elegant.
GavinBelson
10

Gleiche Situation: Nachdem Sie mehrere Angular-Projekte durchgeführt und zu React gewechselt sind, scheint es ein fehlendes Teil zu sein (abgesehen von den Einzelheiten des Dienstes), keine einfache Möglichkeit zu haben, Dienste über DI bereitzustellen.

Mit Kontext- und ES7-Dekoratoren können wir näher kommen:

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

Diese Jungs scheinen einen Schritt weiter gegangen zu sein / in eine andere Richtung:

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

Fühlt sich immer noch an, als würde man gegen den Strich arbeiten. Wird diese Antwort in 6 Monaten nach Durchführung eines großen React-Projekts erneut prüfen.

EDIT: Zurück 6 Monate später mit etwas mehr React Erfahrung. Betrachten Sie die Art der Logik:

  1. Ist es (nur) an die Benutzeroberfläche gebunden? Verschieben Sie es in eine Komponente (akzeptierte Antwort).
  2. Ist es (nur) an die staatliche Verwaltung gebunden? Bewegen Sie es in einen Thunk .
  3. An beide gebunden? In eine separate Datei verschieben, in der Komponente über einen Selektor und in Thunks verbrauchen.

Einige greifen auch nach HOCs zur Wiederverwendung, aber für mich deckt das oben Gesagte fast alle Anwendungsfälle ab. Ziehen Sie auch in Betracht, die Statusverwaltung mithilfe von Enten zu skalieren , um Bedenken getrennt zu halten und die Benutzeroberfläche auf den Status auszurichten.

Blumenkrone
quelle
Ich denke, es gibt eine einfache Möglichkeit, Dienste über DI bereitzustellen, indem das ES6-Modulsystem verwendet wird
Mickey Puri
1
@MickeyPuri, ES6-Modul DI würde die hierarchische Natur von Angular DI nicht enthalten, d. H. Eltern (in DOM) instanziieren und überschreiben Dienste, die für untergeordnete Komponenten bereitgestellt werden. Imho ES6-Modul DI ist näher an Backend-DI-Systemen wie Ninject und Structuremap zu vergleichen, die von der DOM-Komponentenhierarchie getrennt sind und nicht auf dieser basieren. Aber ich würde gerne Ihre Gedanken dazu hören.
Blumenkrone
6

Ich komme ebenfalls aus Angular und probiere React aus. Ab sofort scheint eine empfohlene (?) Methode die Verwendung von Komponenten höherer Ordnung zu sein :

Eine Komponente höherer Ordnung (HOC) ist eine fortschrittliche Technik in React zur Wiederverwendung der Komponentenlogik. HOCs sind per se nicht Teil der React-API. Sie sind ein Muster, das sich aus der kompositorischen Natur von React ergibt.

Angenommen, Sie haben inputund textareamöchten dieselbe Validierungslogik anwenden:

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

Schreiben Sie dann ein HOC, das die umschlossene Komponente validiert und formatiert:

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

Jetzt haben diese HOCs dasselbe Validierungsverhalten:

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

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

Ich habe eine einfache Demo erstellt .

Bearbeiten : Eine andere Demo verwendet Requisiten, um ein Array von Funktionen zu übergeben, sodass Sie die Logik, die aus mehreren Validierungsfunktionen besteht, über HOCs wie folgt gemeinsam nutzen können :

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

Edit2 : React 16.8+ bietet eine neue Funktion, Hook , eine weitere gute Möglichkeit, Logik zu teilen.

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

Bob
quelle
Danke dir. Ich habe wirklich aus dieser Lösung gelernt. Was ist, wenn ich mehr als einen Validator haben muss? Zum Beispiel, wenn ich zusätzlich zu einem 3-Buchstaben-Validator einen anderen Validator haben möchte, der sicherstellt, dass keine Zahlen eingegeben werden. Können wir Validatoren zusammenstellen?
Youssef Sherif
1
@YoussefSherif Sie können mehrere Validierungsfunktionen vorbereiten und als Requisiten von übergeben. Weitere Informationen finden Sie in HOCmeiner Bearbeitung.
Bob
HOC ist also im Grunde eine Containerkomponente?
Sensei
Ja, aus dem React-Dokument: "Beachten Sie, dass ein HOC weder die Eingabekomponente ändert noch die Vererbung verwendet, um sein Verhalten zu kopieren. Vielmehr erstellt ein HOC die ursprüngliche Komponente, indem es sie in eine Containerkomponente einwickelt. Ein HOC ist ein reines Funktion ohne Nebenwirkungen. "
Bob
1
Die Anforderung war, Logik einzufügen, ich verstehe nicht, warum wir ein HOC brauchen, um dies zu tun. Während Sie es mit einem HOC tun können, fühlt es sich überkompliziert an. Mein Verständnis von HOCs ist, wenn es auch einen zusätzlichen Status gibt, der hinzugefügt und verwaltet werden muss, dh keine reine Logik (was hier der Fall war).
Mickey Puri
4

Der Service ist nicht auf Angular beschränkt, auch nicht in Angular2 + .

Service ist nur eine Sammlung von Hilfsfunktionen ...

Und es gibt viele Möglichkeiten, sie zu erstellen und in der gesamten Anwendung wiederzuverwenden ...

1) Sie können alle getrennte Funktionen sein, die aus einer js-Datei exportiert werden, ähnlich wie unten:

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

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

2) Wir können auch eine Factory-Methode wie die Sammlung von Funktionen verwenden. Mit ES6 kann es sich eher um eine Klasse als um einen Funktionskonstruktor handeln:

class myService {

  constructor() {
    this._data = null;
  }

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

  getMyService() {
    return this._data;
  }

}

In diesem Fall müssen Sie eine Instanz mit neuem Schlüssel erstellen ...

const myServiceInstance = new myService();

Auch in diesem Fall hat jede Instanz ihr eigenes Leben. Seien Sie also vorsichtig, wenn Sie es gemeinsam nutzen möchten. In diesem Fall sollten Sie nur die gewünschte Instanz exportieren ...

3) Wenn Ihre Funktion und Dienstprogramme nicht gemeinsam genutzt werden, können Sie sie sogar in die React-Komponente einfügen, in diesem Fall genauso wie die Funktion in Ihrer React-Komponente ...

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

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

4) Eine andere Möglichkeit, mit Dingen umzugehen , könnte die Verwendung von Redux sein . Es ist ein temporärer Speicher für Sie. Wenn Sie ihn also in Ihrer React-Anwendung haben , kann er Ihnen bei vielen Getter-Setter-Funktionen helfen, die Sie verwenden ... Es ist wie ein großer Speicher Das behält den Überblick über Ihre Zustände und kann diese auf Ihre Komponenten verteilen. So können Sie viele Schmerzen für Getter-Setter-Dinge, die wir in den Diensten verwenden, loswerden ...

Es ist immer gut, einen DRY-Code zu erstellen und nicht zu wiederholen, was verwendet werden muss, um den Code wiederverwendbar und lesbar zu machen. Versuchen Sie jedoch nicht, in der React-App , wie in Punkt 4 erwähnt , den Angular-Methoden zu folgen Dienste und Sie beschränken ihre Verwendung für einige wiederverwendbare Hilfsfunktionen wie Punkt 1 ...

Alireza
quelle
Sicher, Sie können es auf meiner persönlichen Website finden, die Link von meiner Profilseite ist ...
Alireza
"Folgen Sie Angular nicht in React". Ahem Angular fördert die Verwendung von Redux und überträgt den Speicher mithilfe von Observables und Redux-ähnlichem Statusmanagement wie RxJS / Store an die Präsentationskomponenten. .. meintest du AngularJS? Weil das eine andere Sache ist
Spock
1

Ich bin im selben Stiefel wie du. In dem von Ihnen erwähnten Fall würde ich die UI-Komponente für die Eingabevalidierung als React-Komponente implementieren.

Ich bin damit einverstanden, dass die Implementierung der Validierungslogik selbst nicht gekoppelt werden sollte (darf). Daher würde ich es in ein separates JS-Modul einfügen.

Das heißt, für Logik, die nicht gekoppelt werden soll, verwenden Sie ein JS-Modul / eine JS-Klasse in einer separaten Datei und verwenden Sie require / import, um die Komponente vom "Dienst" zu entkoppeln.

Dies ermöglicht die unabhängige Abhängigkeitsinjektion und das Testen von Einheiten der beiden.

sibidiba
quelle
1

oder Sie können die Klassenvererbung "http" in React Component einfügen

über Requisiten Objekt.

  1. Update:

    ReactDOM.render(<ReactApp data={app} />, document.getElementById('root'));
  2. Bearbeiten Sie React Component ReactApp einfach wie folgt:

    class ReactApp extends React.Component {
    
    state = {
    
        data: ''
    
    }
    
        render(){
    
        return (
            <div>
            {this.props.data.getData()}      
            </div>
    
        )
        }
    }
Juraj
quelle
0

Nun, das am häufigsten verwendete Muster für wiederverwendbare Logik ist das Schreiben eines Hooks oder das Erstellen einer Utils-Datei. Es hängt davon ab, was Sie erreichen möchten.

hooks/useForm.js

Wenn Sie beispielsweise Formulardaten validieren möchten, würde ich einen benutzerdefinierten Hook mit dem Namen useForm.js erstellen und Formulardaten bereitstellen. Im Gegenzug würde ich ein Objekt zurückgeben, das zwei Dinge enthält:

Object: {
    value,
    error,
}

Sie können definitiv mehr Dinge zurückgeben, wenn Sie Fortschritte machen.

utils/URL.js

Ein anderes Beispiel wäre, als ob Sie einige Informationen aus einer URL extrahieren möchten. Dann würde ich eine Utils-Datei dafür erstellen, die eine Funktion enthält, und sie bei Bedarf importieren:

 export function getURLParam(p) {
...
}
Muhammad Shahryar
quelle