Statische Eingabe in einer React-Anwendung

Im Jahr 2016 begann TypeScript neue Höhen zu erreichen. Die Entwickler begannen, viele gängige Technologien vollständig neu zu schreiben und vorhandenen Plattformen Unterstützung für statische Analysen hinzuzufügen. Ein solcher globaler Prozess hat der Codebasis von Tausenden und sogar Zehntausenden von Projekten mehr Stabilität verliehen.

Warum reagieren? Bis heute dominiert diese Bibliothek zweifellos vor dem Hintergrund der Wettbewerber. Rund um React hat sich die größte Entwicklergemeinschaft der Welt gebildet. Jedes dritte SPA ist auf dieser Plattform geschrieben. Es gibt auch viele großartige Projekte im Zusammenhang mit der Verwendung von React Native, einer Plattform für iOS-, UWP- und Android-Anwendungen, die auf React.js basiert.

Daher werden wir uns heute die Möglichkeiten ansehen, die die Integration von zwei sehr beliebten Tools bietet: TypeScript und React.



Beispiele


Lassen Sie uns zunächst sehen, welche Typen wir für React verwenden können.
Beginnen wir einfach und fügen der Funktionskomponente Typen hinzu.

import * as React from 'react'; const HelloWorld: React.FunctionComponent<{ name: string; }> = ({ name = 'World' }) => { return <div>Hello, {props.name}</div>; }; export default HelloWorld; 

Für Functional Component oder Statless Component müssen wir eine Definition vom Typ React.FunctionComponent verwenden. Wir können auch Typen für das Requisitenargument definieren - Felder, die die Komponente an die Komponente übergibt. In diesem Fall können Requisiten nur ein Namensfeld vom Typ Zeichenfolge enthalten.

Das alles sieht nicht kompliziert aus. Was ist mit Klassenkomponenten?

 import * as React from 'react'; interface State { name: string; } interface Props {} class HelloWorld extends React.Component<Props, State> { state = { name: 'World' } setName(name: string) { this.setState({ name }); } redner() { return ( <React.Fragment> <hI>Hello, {this.state.name}</hI> <input value={this.state.name} onChange={(e) => this.setName(e.target.value)} /> </React.Fragment> ); } } 

Im Klassenbeispiel haben wir zwei Schnittstellen erstellt: Requisiten und Status. Mit ihrer Hilfe haben wir die Signaturen eingehender Requisiten (leer) und die Signatur des Status der Komponente ermittelt - wie im Beispiel mit Funktionskomponenten.

Wir können auch Standardwerte für Requisiten hinzufügen.

 import * as React from 'react'; interface Props { name?: string; } export default class HelloWorld extends React.Component<Props> { static defaultProps: Props = { name: 'World' }; render () { return <hI>Hello, {this.props.name}</hI>; } } 

Das ist alles! Unsere kleine React-Anwendung ist bereits auf der Ebene der Parameter und Komponentenstatuswerte stark typisiert.

Schauen wir uns die Vorteile an, die sich daraus ergeben haben:

  • In der Kompilierungsphase werden alle Typinkongruenzen angezeigt.
  • Ein ordnungsgemäß konfigurierter Editor hilft uns, Fehler bereits in der Entwicklungsphase zu vermeiden, indem einfach die Diskrepanzen zwischen Signaturen oder Datentypen hervorgehoben werden.
  • Dokumentation von Schnittstellen und Typdefinitionen.


Aufzählung der Parameter



Enum ist ein aufgezählter Datentyp. Wenn wir diesen Typ zu einer Variablen oder einem Schnittstellenfeld hinzufügen, kann der Wert dieses Feldes oder dieser Variablen nur bestimmte Werte in Enum sein.
Zum Beispiel.

  import * as React from 'react'; enum Colors { RED, BLUE, GREEN } const ColorResult: React.FunctionComponent<{ color: Colors; }> = ({ color = Colors.Red }) => { return <div>Your color is {props.color}</div>; }; export default ColorResult; 

In der bereits bekannten Funktionskomponente möchten wir die vom Benutzer ausgewählte Farbe anzeigen. Im Typ enum Colors haben wir alle möglichen Farboptionen angegeben, die an die Komponente übertragen werden können. Wenn der TypeScript-Compiler irgendwo eine Typinkongruenz feststellt, wird dies mit einem Fehler angezeigt.

Strenger Redux


Im Jahr 2019 laufen noch viele Anwendungen auf Redux. TypeScript kann in dieser Situation helfen.

 import * as React from 'react'; const initialState = { name: 'World' }; type HelloWorldStateProps = Readonly<typeof initialState>; interface Action { type: string; name?: string; } const worldNameReducer = ( state: HelloWorldStateProps = initialState, action: Action ): HelloWorldStateProps => { switch (action.type) { case "SET": return { name: action.name }; case "CLEAR": return { name: initialState.name }; default: return state; } }; const set = (name): Action => ({ type: "SET", name }); const clear = (): Action => ({ type: "CLEAR" }); const store = createStore( combineReducers({ world: worldNameReducer }) ); type StateProps = ReturnType<typeof mapStateToProps>; type DispatchProps = typeof mapDispatchToProps; interface AppProps extends StateProps, DispatchProps {} interface AppState extends StateProps {} class App extends React.Component<AppProps, AppState> { state = { name: initialState.name } setName(name: string) { this.setState({ name }); } render() { const { set, clear, name } = this.props; return ( <div> <hI>Hello, {name}</hI> <input value={this.state.name} onChange={(e) => this.setName(e.target.value)} /> <button onClick={() => set(this.state.name)}>Save Name</button> <button onClick={() => clear()}>Clear</button> </div> ); } } const mapStateToProps = ({ world }: { world: HelloWorldStateProps }) => ({ name: world.name, }); const mapDispatchToProps = { set, clear }; const AppContainer = connect( mapStateToProps, mapDispatchToProps )(App); render( <Provider store={store}> <AppContainer /> </Provider>, document.getElementById("root") ); 

In diesem Beispiel fügen wir der Anwendung auf mehreren Ebenen gleichzeitig Typen hinzu. Zuallererst sind es die Reduzierer selbst. Der Eingangsreduzierer akzeptiert Action und muss immer ein Objekt zurückgeben, das dem Typ HelloWorldStateProps entspricht. Angesichts der Anzahl der Reduzierstücke in einer modernen Anwendung ist dies eine sehr nützliche Innovation. Außerdem hat jede Aktion, die wir haben, eine strikte Aktionssignatur.

Die nächste Eingabeebene ist die Komponente. Hier haben wir die Typvererbung auf AppProps und AppState angewendet. Warum mehr schreiben, wenn wir bereits Datentypen mit solchen Signaturen haben? Es ist einfacher, das System zu warten. Wenn Sie einige Elemente ändern, werden Änderungen für alle Erben vorgenommen.

Fazit


TypeScript ist eine sehr nützliche Sprache, die über JavaScript ausgeführt wird. In Verbindung mit React bietet es wirklich beeindruckende Programmierpraktiken für Frontend-Anwendungen.

Source: https://habr.com/ru/post/de465461/


All Articles