React-Redux mit TypeScript

Blog

React-Redux mit TypeScript

React-Redux mit TypeScript

TypeScript ist eine typisierte Obermenge von JavaScript. Es ist in letzter Zeit aufgrund der Vorteile, die es mit sich bringen kann, in Anwendungen populär geworden. Wenn Sie mit TypeScript noch nicht vertraut sind, wird dringend empfohlen, sich zuerst damit vertraut zu machen, bevor Sie fortfahren.

TypeScript ist eine großartige Sprache, die Sie wählen können, wenn Sie ein JavaScript-Entwickler sind und an einer statisch typisierten Sprache interessiert sind. Die Verwendung von TypeScript ist ein logischer Schritt für Entwickler, die mit JavaScript vertraut sind, aber nicht in Sprachen geschrieben haben, die statisch typisiert sind (wie C, JVMs, Go usw.).

Als ich meine Reise zu TypeScript begann (ich bin mit JS am vertrautesten, habe aber ein wenig in Go und C geschrieben), fand ich es ziemlich einfach, es zu erlernen. Mein erster Gedanke war: Es ist wirklich nicht so schlimm, alle Argumente in meiner Funktion einzugeben und den Rückgabewert einzugeben; worum geht es? Es war schön und einfach, bis wir ein Projekt hatten, bei dem wir eine React/Redux-App in TypeScript erstellen mussten.

Es ist super einfach, Material für React + JS zu finden, aber wenn Sie anfangen, nach React + TS und insbesondere nach React + Redux + TS zu suchen, nimmt die Anzahl der Online-Tutorials (einschließlich YouTube-Videos) erheblich ab. Ich durchsuchte Medium, Stack Overflow usw. nach allem, was ich finden konnte, um zu erklären, wie das Projekt eingerichtet wird, wie Typen zwischen Dateien fließen (insbesondere wenn Redux beteiligt ist) und wie man mit Webpack baut. Dieser Artikel ist eine Möglichkeit für mich, mein Wissen über React + Redux + TS zu festigen und hoffentlich allen anderen, die daran interessiert sind, diesen Tech-Stack für das Frontend zu verwenden, eine Anleitung zu geben. TypeScript wird immer beliebter, daher hoffe ich, dass dies für andere in der Community nützlich ist.

Voraussetzungen: Ich gehe davon aus, dass Sie wissen, wie React, Redux und Webpack funktionieren und auch die meisten Konzepte in TypeScript (zumindest Schnittstellen und Generics).

Was werden wir bauen? Um es einfach zu halten, erstellen wir die berüchtigte To-Do-Listen-Anwendung. Denken Sie daran, dass der Zweck darin besteht, zu verstehen, wie das Projekt eingerichtet wird und wie TypeScript in React und Redux integriert wird. Die Funktionen, die diese Anwendung unterstützt, sind:

  1. Fügen Sie einer Liste ein neues Element hinzu.
  2. Entfernen Sie ein Element aus der Liste.

Den Code für das Projekt finden Sie hier: https://github.com/sterlingdeng/react-redux-ts-boilerplate .

Für mein Projekt habe ich |_+_| . nicht verwendet um das Projekt zu starten. Ich fand, dass es eine wertvolle Lernerfahrung war, es von Grund auf neu zu beginnen. Ich werde Schritt für Schritt die Importdateien und -ordner durchgehen, die zum Ausführen dieses Projekts erforderlich sind. Bevor wir beginnen, möchte ich Ihnen zeigen, wie die endgültige Struktur aussieht.

create-react-app --typescript

Schauen wir uns zuerst die |_+_| . an Datei und installieren Sie diese Abhängigkeiten mit |_+_|.

TS-Redux-React-Boilerplate ├── build ├── node_modules ├── public │ ├── bundle.js │ └── index.html ├── src │ ├── App.tsx │ ├── index.tsx │ ├── actions │ │ ├── actions.ts │ │ └── index.ts │ ├── components │ │ ├── index.ts │ │ └── TodoItem.tsx │ ├── containers │ │ └── TodoContainer.tsx │ ├── reducers │ │ ├── index.ts │ │ └── todoReducers.ts │ ├── store │ │ └── store.ts │ └── types │ └── types.d.ts ├── .gitignore ├── package-lock.json ├── package.json ├── tslint.json ├── tsconfig.json ├── webpack.config.js └── README.md

Schauen wir uns zunächst die Abhängigkeiten mit dem Format |_+_| an. Wenn Sie mit diesen Modulen nicht vertraut sind, schauen Sie nach https://github.com/DefinitelyTyped/DefinitelyTyped . Da die meisten Module in JavaScript geschrieben sind, werden sie nicht mit den richtigen Typdefinitionen geschrieben. Sobald Sie versuchen, ein Modul ohne Typinformationen in ein vollständig typisiertes Projekt zu importieren, wird sich TypeScript beschweren. Um dies zu verhindern, erstellt die Community von Mitwirkenden bei DefinitelyTyped qualitativ hochwertige Typdefinitionen der am häufigsten verwendeten JavaScript-Module, damit diese Module so nahtlos wie möglich in TS integriert werden.

Sie kennen wahrscheinlich die nächsten vier. |_+_| wird benötigt, da Webpack ein Plugin zum Parsen von |_+_| . benötigt und |_+_| Dateien. (Dies ähnelt |_+_|.)

|_+_| ist eine Bibliothek, die ich mit Redux + TypeScript verwende. Ohne sie können die Dateien in Bezug auf die Deklaration von Typen für Store, Reducer und Actions ziemlich verrauscht werden. Diese Bibliothek stellt Methoden bereit, die Typdefinitionen für Redux-Code ableiten, damit die Dateien etwas sauberer und fokussierter sind.

|_+_| und |_+_| werden verwendet, um die |_+_| . zu bündeln und |_+_| Dateien in eine|_+_|Datei, die an das Frontend gesendet werden kann.

mywifiext erfolgreich eingerichtet

Schauen wir uns als Nächstes die|_+_| . an Datei. Der Zweck dieser Datei besteht darin, zu konfigurieren, wie der ts-Compiler ausgeführt werden soll.

package.json

|_+_| bezeichnet den Ordner. |_+_| weist den Compiler an, wo er den kompilierten Code ablegen soll. |_+_| teilt dem Compiler mit, welche JavaScript-Modultypen verwendet werden sollen. |_+_| teilt dem Compiler mit, welche JS-Version als Ziel verwendet werden soll. |_+_| weist den Compiler an, ein |_+_| . zu erstellen zusammen mit |_+_|. Da durch die Bündelung mehrere Dateien in eine große .js-Datei umgewandelt werden, wird die Fehlerbehebung im Code schwierig, da Sie nicht leicht wissen würden, welche Datei und an welcher Zeile der Code fehlgeschlagen ist (da alles nur eine große Datei ist). Die |_+_| file ordnet die gebündelte Datei der jeweiligen ungebündelten Datei zu.

|_+_| bietet Optionen, wie streng oder locker der ts-Linter sein soll. Die verschiedenen Optionen, die Sie für den Linter einstellen können, finden Sie online.

Aktionsersteller

Wenn ich Projekte mit Redux starte, fange ich normalerweise bei den Action Creators an. Sehen wir uns kurz die Funktionen an, die wir implementieren müssen: Hinzufügen eines Elements zu einer Liste und Entfernen eines Elements aus der Liste. Das bedeutet, dass wir zwei Aktionsersteller benötigen, einen zum Hinzufügen und einen zum Entfernen.

npm i

In der Datei action.ts verwende ich das |_+_| Feature in TS, um die Aktionskonstanten zu erstellen. Zweitens verwende ich das |_+_| Methode aus dem |_+_| Modul. Das erste Argument, das Sie an die Methode übergeben, ist eine Zeichenfolge, die diese Aktion darstellt, und das zweite Argument ist die Nutzlast. Die |_+_| -Methode fügt ein Element zur Liste der Aufgaben hinzu, und die Methode |_+_| entfernt ein Element basierend auf dem angegebenen Index aus der Liste der Aufgaben.

In Bezug auf die Typensicherheit wollen wir in unserer Reduzierdatei die richtige Typ der Nutzlast, bei einem bestimmten Handlung . Die Funktion in TypeScript, die diese Unterstützung bietet, heißt diskriminierte Gewerkschaft und Typschutz . Betrachten Sie das folgende Beispiel:

'dependencies': { '@types/node': '^12.0.0', '@types/react': '^16.8.15', '@types/react-dom': '^16.8.4', '@types/react-redux': '^7.0.8', 'react': '^16.8.6', 'react-dom': '^16.8.6', 'react-redux': '^7.0.3', 'redux': '^4.0.1', 'ts-loader': '^5.4.5', 'typesafe-actions': '^4.2.0', 'typescript': '^3.4.5', 'webpack': '^4.30.0', 'webpack-cli': '^3.3.1' }

Angesichts der Form der beiden Aktionsobjekte können wir zwischen ihnen anhand der |_+_| . unterscheiden Eigentum. Verwenden von Kontrollflussanalysen wie |_+_| oder |_+_| -Anweisungen ist es sehr logisch, dass in Zeile 16 der einzige Typ der Nutzlast ein String sein kann. Da wir nur zwei Aktionen haben, ist die verbleibende Nutzlast in Zeile 22 eine Zahl. Wenn Sie daran interessiert sind, mehr über diskriminierte Gewerkschaften und Typenschutz zu erfahren, würde ich empfehlen, mehr darüber zu erfahren Hier und Hier .

Reduzierstück

Nachdem wir unsere Action Creators definiert haben, erstellen wir den Reducer für dieses Projekt.

@types/[npm module here]

In den Zeilen vier bis sieben definiere ich das Modell (oder Schema) unseres |_+_|Geschäfts. Es wird verfolgen, wie viele To-Do-Elemente wir haben, sowie das Array von Strings. Die Zeilen neun bis 12 sind der Ausgangszustand beim ersten Start der Anwendung. Innerhalb der |_+_| -Funktion wollen wir Typsicherheit innerhalb der |_+_|-Anweisungen. Basierend auf dem früheren Kern haben wir dies durch diskriminierte Vereinigungen und Typschutz erreicht, indem wir |_+_| . eingeben Parameter. Wir müssen zuerst für jedes Aktionsobjekt eine Schnittstelle definieren und dann eine Vereinigung aller erstellen und diese einem Typ zuweisen. Das kann mühsam werden, wenn wir viele Action-Ersteller haben – zum Glück |_+_| verfügt über Methoden, die dabei helfen, die richtige Typisierung der Aktionsersteller zu erstellen, ohne tatsächlich alle Schnittstellen schreiben zu müssen.

ts-loader

Wir ignorieren Zeile vier vorerst und konzentrieren uns auf Zeile fünf. Wir verwenden eine Methode namens |_+_| aus dem Modul und importieren Sie die Aktionen aus |_+_| um die diskriminierten Unionstypen zu erzeugen, die dann einem Typ namens |_+_| zugewiesen werden. In Zeile eins der todoReducers.ts importieren wir |_+_| und in Zeile 14 geben wir die |_+_| Parameter mit |_+_|. Dies ermöglicht uns IntelliSense und Autovervollständigung in den Reduzierern!

Nachdem wir nun den Reduzierer eingerichtet haben, wird der |_+_| tippe aus dem |_+_| -Datei ermöglicht TypeScript, die Form des Zustandsobjekts in der Reducer-Funktion abzuleiten. Dadurch wird IntelliSense bereitgestellt, wenn wir versuchen, auf das Nutzlastobjekt im Reducer zuzugreifen. Ein Beispiel dafür, wie das aussieht, ist im Bild unten.

IntelliSense im Reduzierstück

Redux-Store

Schließlich schließen wir den Reducer an den Redux Store an.

.ts

Fassen wir zusammen, was wir bisher erreicht haben. Wir haben unsere Aktionsersteller mit dem |_+_| . erstellt und eingegeben Methode von |_+_|. Wir haben unsere |_+_| . erstellt Datei, die Typinformationen zu unserem Action-Ersteller und Reduzierzustand . Der Reducer wurde erstellt und die Aktionen werden mit |_+_| eingegeben, die unschätzbare Informationen zur automatischen Vervollständigung der Nutzlast in den Case-Anweisungen des Reducers liefern. Und schließlich haben wir unseren Redux-Shop erstellt.

Reagieren und TS

Lassen Sie uns die Gänge wechseln und mit der Erstellung und Eingabe unserer React-Komponenten beginnen. Ich werde Beispiele durchgehen, wie man beide richtig eingibt Funktion und Klasse basierende Komponenten, zusammen mit Anweisungen zum Eingeben der Eigenschaften und des Zustands (für zustandsbehaftete Komponenten).

App.tsx

.tsx

|_+_| ist eine funktionale Komponente, die durch Schreiben von |_+_| typisiert wird. (FC bezieht sich auf funktionale Komponenten.) Wenn Sie mit Generics (das ist das |_+_| ) nicht vertraut sind, halte ich sie für Variablen, aber für Typen. Da die Form von |_+_| und |_+_| können sich je nach Anwendungsfall unterscheiden, Generika sind für uns eine Möglichkeit, die Komponente generisch zu machen! In diesem Fall |_+_| braucht keine Requisiten; daher übergeben wir ein leeres Objekt als generisches Objekt. Woher wissen wir, dass das Generikum speziell für Requisiten gedacht ist? Wenn Sie VS-Code verwenden, teilt Ihnen IntelliSense mit, welcher Typ benötigt wird.

Wo steht |_+_| , es bedeutet Typ |_+_| wurde P zugewiesen, wobei |_+_|für Requisiten steht. Für klassenbasierte Komponenten verwendet React |_+_| auf den Staat verweisen. |_+_| ist eine funktionale Komponente, die keine Requisiten erhält und nicht mit dem Redux-Store verbunden ist. Nehmen wir etwas Komplizierteres.

TodoContainer.tsx

babel

Okay, |_+_| ist die komplizierteste von allen, aber ich werde Sie durch den Code führen. |_+_| ist eine React-Klassenkomponente, weil ich sie benötige, um den Wert für das Eingabefeld in ihrem Zustand zu halten. Es ist auch mit dem Redux Store verbunden, also hat es |_+_| und |_+_| . Zuerst habe ich definiert|_+_| . Da ich den Wert des Eingabefelds im Zustand behalte, gebe ich die Eigenschaft als Zeichenfolge ein.

Reagieren-Native-Fortschritt-Kreis

Als Nächstes habe ich |_+_| definiert, was die Form der Requisiten des Containers sein wird.

Da klassenbasierte Komponenten sowohl Zustände als auch Props haben können, sollten wir erwarten, dass es mindestens zwei Generics gibt, die wir an |_+_| übergeben müssen.

P für Requisiten und S für Staat

Wenn Sie mit der Maus über |_+_| fahren, können Sie sehen, dass es drei Generics enthält, |_+_|, |_+_| und |_+_|. Die ersten beiden Generika sind Requisiten und Zustand. Ich bin mir nicht ganz sicher was|_+_| ist und was der Anwendungsfall ist. Wenn es jemand weiß, lass es mich bitte in den Kommentaren unten wissen.

Nach der Übergabe der Generika in |_+_| , IntelliSense und Autovervollständigung funktionieren innerhalb von |_+_| und für |_+_|.

Als nächstes wollen wir |_+_| . eingeben und |_+_|. Dies ist leicht zu erreichen, indem Sie die |_+_| Modul, das wir in der Redux-Sektion gebaut haben. Für |_+_| weisen wir die |_+_| Geben Sie |_+_| ein. Ein Beispiel für den IntelliSense, der bereitgestellt wird, finden Sie im folgenden Screenshot.

IntelliSense für MapStateToProps

Schließlich wollen wir die Typsicherheit innerhalb von |_+_| haben. Der bereitgestellte Vorteil ist eine typsichere Nutzlast bei einem gegebenen Aktionstyp.

Typsichere Nutzlasten

Im obigen Screenshot habe ich absichtlich |_+_| . eingegeben als boolescher Wert. Der TSServer erkennt sofort, dass die boolesche Nutzlast innerhalb von |_+_| ist nicht korrekt, da erwartet wird, dass die Nutzlast ein String ist, da der Typ |_+_| ist. |_+_| am meisten los ist, da es sich um eine klassenbasierte React-Komponente handelt, die sowohl Zustand als auch Props enthält und auch mit dem Store verbunden ist.

Bevor wir zum Abschluss kommen, schauen wir uns unsere letzte Komponente an: |_+_|

TodoItem.tsx

Diese Komponente ist eine funktionale Komponente mit Requisiten – Code unten.

typesafe-actions

Die Form der Requisiten wird im Interface |_+_| definiert. Die Typinformationen werden generisch in |_+_| übergeben. Dadurch wird eine automatische Vervollständigung für |_+_| . bereitgestellt innerhalb der Komponente. Fantastisch.

Eine weitere großartige Funktion, die TypeScript bei Verwendung mit React bietet, ist IntelliSense für Requisiten beim Rendern von React-Komponenten in JSX. Wenn Sie beispielsweise |_+_| . löschen von |_+_| und dann zu |_+_| navigieren, wird an der Stelle, an der Sie |_+_| rendern, ein Fehler angezeigt.

Eigenschaft 'idx' existiert nicht

Weil wir |_+_| . entfernt haben aus dem |_+_| Interface teilt uns TypeScript mit, dass wir eine zusätzliche Requisite, die es nicht finden konnte, |_+_|, in der Komponente bereitgestellt haben.

Als letztes erstellen wir das Projekt mit Webpack. Geben Sie in der Befehlszeile |_+_| ein. Im |_+_| Ordner im Stammverzeichnis sollten Sie |_+_| . sehen neben|_+_|. Öffnen |_+_| in jedem Browser und Sie sollten eine sehr einfache, ungestylte To-Do-App sehen.

Google Maps nicht aktualisiert

Nach dem Webpack-Build

Ich hoffe, dass ich die Leistungsfähigkeit von TypeScript in Verbindung mit React und Redux demonstrieren konnte. Es mag für unsere einfache To-Do-Listen-App etwas übertrieben erscheinen – Sie müssen sich nur den Vorteil von TS + React + Redux im großen Maßstab vorstellen. Es wird neuen Entwicklern helfen, den Code schneller zu lesen, mehr Vertrauen in das Refactoring zu schaffen und letztendlich die Entwicklungsgeschwindigkeit zu verbessern.

Wenn Sie mehr Referenz und Material benötigen, habe ich die folgenden zwei verwendet gehen sich ausruhen mich selbst beibringen

Beide Repos haben sich für mein Lernen als von unschätzbarem Wert erwiesen, und ich hoffe, sie werden für Sie gleich sein.

#redux #reactjs #typescript #javascript