Tauchen Sie ein in React Native für die Android-Entwicklung
Veröffentlicht: 2022-03-11Vor ein paar Jahren hat mir ein Kollege von React Native erzählt. Ich war sehr skeptisch. Ich argumentierte, dass es nur ein weiteres plattformübergreifendes Framework ist, das im wirklichen Leben niemals funktionieren wird – ich wusste nicht, wie falsch ich lag.
Die Jahre vergingen und React Native-Fähigkeiten wurden sehr gefragt. Da es eine Weile her war, dass ich etwas Neues gelernt hatte, dachte ich, warum es nicht versuchen? Heute bin ich ein großer Befürworter von React Native.
Nachteile:
- Sie können Android Studio nicht mehr verwenden
- React Native kann nicht für jede Anwendung oder Funktion verwendet werden
- React Native ist ein neuartiges Framework und Updates können sich negativ auf Ihre aktuelle Codebasis auswirken
- JavaScript ist keine strikt typisierte Sprache
- React Native erfordert eine JavaScript-Engine, um ausgeführt zu werden, wodurch es möglicherweise weniger leistungsfähig ist
Vorteile:
- Leicht zu lernen
- Eine gemeinsame Codebasis zwischen Android- und iOS-Apps, mit nur geringfügigen Anpassungen, die erforderlich sind, um Plattformerfahrungen abzugleichen
- Live- und Hot-Reloading, d. h. keine unendlichen Build-Zeiten mehr
- Native Komponenten für beide Plattformen
- Ständige Verbesserung
- Aktiv wachsende Community
- Riesige Anzahl von Bibliotheken
- Expo beseitigt die Notwendigkeit, einen Mac zu besitzen, um für iOS zu entwickeln
- Reduzierung der Arbeitsressourcen – obwohl Sie möglicherweise noch einige native Android/iOS-Entwicklungen benötigen, wird dies selten der Fall sein.
Ich kann weiter und weiter gehen, aber lassen Sie uns hier aufhören und zum Thema dieses Blogbeitrags übergehen. In diesem Beitrag werde ich vier auf React Native basierende Android-Apps erstellen:
- Ein einfacher Zähler mit Schaltflächen zum Erhöhen und Verringern des Zählers
- Eine App zum Durchsuchen des r/pics-Subreddit
- Eine generische Anmeldeseite
- Eine App zum Durchsuchen des r/pics-Subreddit
IDE
Wie ich oben erwähnt habe, gibt es keine Möglichkeit, Android Studio für die Entwicklung von React Native zu verwenden. Wir brauchen einen Ersatz. React Native kann wahrscheinlich in jedem modernen Texteditor entwickelt werden (Atom, VS Code, Sublime Text, Brackets usw.), aber da wir mit Android Studio Erfahrung kommen, ist mein Favorit WebStorm, das von derselben Firma entwickelt wurde. Obwohl WebStorm eine kostenpflichtige Anwendung ist (129 $ pro Jahr), können Sie die Early-Access-Version davon installieren. EAP-Build von WebStorm ist kostenlos und recht stabil. Wenn Sie einen völlig kostenlosen Editor bevorzugen, entscheiden Sie sich für VS Code. Microsoft hat sogar ein erstaunliches React Native Plugin dafür entwickelt und es funktioniert sehr gut.
Erstellen eines neuen Projekts
Voraussetzungen: Android SDK, Node und React Native auf Ihrem Computer installiert.
Es gibt zwei Möglichkeiten, ein neues React Native-Projekt zu erstellen.
- Der konventionelle Weg. Entweder mit der WebStorm-GUI oder mit dem Terminalbefehl:
react-native init AwesomeToptalProject
- Einfacherer Weg „Create React Native App“.
create-react-native-app AwesomeToptalProject
Wenn Sie create-react-native-app
verwenden, wird das erstellte Projekt mit expo gebootstrapped. Ich werde nicht ins Detail gehen, aber im Grunde bedeutet es, dass Sie Xcode nicht installiert haben müssen, um die App auf iOS auszuführen. Es ist auch einfacher, den Client durch die Funktionalität von expo.io und einige andere Features immer auf dem neuesten Stand zu halten. Sie können jedoch keinen nativen Code hinzufügen. Wenn Sie also ein bestimmtes Feature entwickeln, müssen Sie möglicherweise eine App aus der Expo entfernen und stattdessen ein reguläres React Native-Projekt verwenden.
Ich werde die erste Methode verwenden.
Lassen Sie uns das Projekt ausführen. Öffnen Sie zunächst einen Emulator oder schließen Sie das Gerät an. Wenn Sie das Projekt mit der WebStorm-GUI erstellt haben, müssen Sie lediglich eine Konfiguration auswählen. Klicken Sie in der rechten oberen Ecke von WebStorm auf das Dropdown-Menü links neben der Schaltfläche „Ausführen“, wählen Sie „Android“ und klicken Sie auf „Ausführen“ oder „Debuggen“. Wenn Sie das Projekt mit Terminal erstellt haben, können Sie entweder eine neue React Native-Konfiguration hinzufügen oder sie mit Terminal ausführen:
cd AwesomeToptalProject react-native run-android
Wenn alles gut gelaufen ist, werden Sie mit dem folgenden Bildschirm begrüßt:

Struktur und Grundeinstellung
Bemerkenswerte Elemente innerhalb des Projekts sind:
- android – Android Studio-Projekt, vorkonfiguriert mit React Native-Unterstützung.
- ios – Xcode-Projekt vorkonfiguriert mit React Native-Unterstützung.
- node_modules – Ein Ordner, der das React Native-Framework und andere Javascript-Bibliotheken enthält.
- index.js – Ein Einstiegspunkt für unsere App.
- App.js – Anfangskomponente geladen.
Lassen Sie uns einen Ordner „src“ im Stammverzeichnis des Projekts erstellen und App.js dorthin verschieben. Sie müssen index.js-Importe aktualisieren, damit sie mit dem neuen App.js-Speicherort übereinstimmen.
import App from './src/App';
Löschen Sie alles in App.js und fügen Sie diesen Code ein:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }
Der Code, den wir eingefügt haben, ist ziemlich einfach. Wir haben eine Klasse App
(untergeordnet von React.Component
) erstellt, die die Methode render()
überschreibt und die Text
zurückgibt. React.Component
ist die Basisklasse zum Erstellen von Benutzeroberflächen mit JSX. Der Modifizierer export default
macht die Klasse public
.
Wir können jetzt mit der Gestaltung unseres Layouts beginnen.
Layout mit Flexbox
Flexbox
ähnelt LinearLayout
, aber Flexbox
geht weit über die Fähigkeiten von LinearLayout
hinaus.
Dieser Ausschnitt von JSX:
<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7' }}/> </View>
Rendert dieses Layout:
Während dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Rendert dies:
JSX-Code kommt mir bekannt vor, oder?! Lassen Sie uns ein „Wörterbuch“ (oder ein Cheatsheet) für Layouts erstellen, die in JSX und Android XML ähnlich aussehen.
Bitte beachten Sie, dass die Funktionalitäten nicht unbedingt gleich sind. Ich versuche, den React Native-Neulingen zu helfen, die Idee des Layoutsystems in React Native zu verstehen. Ausführliche Informationen finden Sie im offiziellen Leitfaden.
Betrachten Sie diese JSX-Eigenschaft:
flex: 1
Es ist äquivalent zu diesem:
android:layout_width="match_parent" android:layout_height="match_parent"
Dieser Ausschnitt von JSX:
<View style={{flex: 1, flexDirection: 'row'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Und dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Beide erzeugen diese Ausgabe:
Ähnlich dieser JSX:
<View style={{flex: 1, flexDirection: 'column'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Und dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Generieren Sie dies:
Um die richtige Position innerhalb des Containers zu erreichen, verwenden wir am häufigsten eine Kombination aus den Eigenschaften flexDirection
, alignItems
und justifyContent
.
Diese JSX:
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Und dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Wird dieses Layout erstellen:
Diese JSX:
<View style={{flex: 1, flexDirection: 'column', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Und dieses XML
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Wird dieses Layout erstellen:
Diese JSX:
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Und dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Wird dieses Layout erstellen:
Diese JSX:
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
und dieses XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Wird dieses Layout erstellen:
Zu lernende Lektion: Wenn wir flexDirection: row',
funktioniert alignItems works on Y axis and
justifyContent works on X axis. Everything is mirrored for
works on X axis. Everything is mirrored for
: column' - justifyContent
wirkt sich auf die Y-Achse aus und alignItems
wirken sich auf die Y-Achse aus.
justifyContent: 'flex-start' | Schwerkraft="start|links" |
alignItems: 'flex-start' | Schwerkraft="start|links" |
justifyContent: 'Flex-Ende' | Schwerkraft="Ende|Rechts" |
alignItems: 'Flex-Ende' | Schwerkraft="Ende|Rechts" |
Versuch es selber. Legen Sie den justifyContent
-Wert auf space-around
, space-between
und space-evenly
fest.
Staatsverwaltung
Zum Aktualisieren des Anwendungsstatus verwenden Sie state
Statusvariable von React. Immer wenn state
aktualisiert wird, wird render()
aufgerufen.
Kopieren Sie den folgenden Code in Ihre App:
import React from 'react'; import {Button, Text, View} from 'react-native'; export default class App extends React.Component { /* Initialize state object with variable 'number' set to 0 and variable name with value of empty string */ state = {number: 0}; render() { return ( <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', flex: 1, padding: 20 }}> <Button title='Decrement' color='#e57373' onPress={() => this.decrement()}/> <Text> {/* Text will be automatically updated whenever state.number has changed value */} Value = {this.state.number} </Text> <Button title='Increment' color='#64B5F6' {/* Set listener for click */} onPress={() => this.increment()}/> </View> ); } //Declaration of decrement function decrement() { //To update the state we need invoke this.setState //with new value for variable 'number' this.setState({number: this.state.number - 1}); } increment() { this.setState({number: this.state.number + 1}); } }

Wenn Sie auf die Schaltflächen DECREMENT und INCREMENT klicken, sehen Sie, dass der Text automatisch für Sie aktualisiert wird. Es besteht keine Notwendigkeit, textView.setText("Value " + number)
explizit zu verwenden.

Die Statusfunktionalität ist aus mehreren Gründen praktisch:
- Einfaches Abrufen des Werts – Sie wissen immer, wo und wie Sie den Wert für eine bestimmte Variable abrufen.
- Daten sind nicht an bestimmte Widgets gebunden.
- Mehrere Widgets abhängig von der gemeinsamen Wertänderung haben.
Erstellen einer Such-App für /r/pics
Nachdem wir nun die Grundlagen im Griff haben, wollen wir etwas Komplexeres erstellen: eine Such-App für /r/pics. Reddit bietet einen unkomplizierten JSON-API-Endpunkt, sodass wir keine Nebenquests durchführen müssen, um eine Authentifizierung zu erhalten, damit es richtig funktioniert.
React Native bietet eine integrierte Fetch-API. Da die meisten von uns wahrscheinlich an Retrofit und seine Benutzerfreundlichkeit gewöhnt sind, verwenden wir axios . Sie können Axios über einen Terminalbefehl installieren
mit yarn
(meine bevorzugte Methode):
yarn add axios
oder mit npm
:
npm install axios
Importe:
import React from 'react'; import { TextInput, View, Text, Image, ActivityIndicator, Platform, StyleSheet } from 'react-native'; import axios from 'axios'; TextInput = EditText, ActivityIndicator = ProgressBar Platform - Platform detecting module StyleSheet - Module for creating stylesheets and moving them away from JSX
Erstellen Sie die Klasse:
export default class App extends React.Component { }
Zustand initialisieren. Wir brauchen:
- loading - Zum Anzeigen eines Fortschrittsbalkens.
- error – Zeigt an, ob bei einer REST-API-Anforderung ein Fehler aufgetreten ist.
- imgUrl – Vorschau des gesuchten Bildes.
- Text - Suchanfrage.
state = {text: '', loading: false, error: null, imgUrl: null};
Fügen Sie den JSX-Code hinzu. Wir haben ein vertikales Layout mit TextInput
und Image
Komponenten.
render() { return ( //Predefined style. See below <View style={styles.containerStyle}> {/* returnKeyType ~ imeOptions onSubmitEditing ~ et.OnEditorActionListener */} <TextInput style={styles.textInputStyle} placeholder="Enter text to search an image" returnKeyType='search' autoFocus={true} onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()}/> {/* Render error Image component if this.state.imgUrl is not equal to null */} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> } </View> ); }
Neue Sachen:
onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }
Die erste Methode funktioniert ähnlich wie EditText
mit der TextWatcher
Komponente. Seien wir ehrlich, in React Native ist es viel schöner.
Die zweite Methode wird aufgerufen, wenn die Eingabetaste auf der Tastatur ( et.OnEditorActionListener
) gedrückt wird, nachdem sie searchPicture searchPicture()
ausgelöst hat.
Das Bild wird gerendert, wenn imgUrl
nicht null oder undefiniert ist, da der Operator „&&“ nicht nach einem zweiten Argument sucht, wenn das erste bereits falsch ist.
Sie fragen sich vielleicht, warum this.state.imgUrl
falsch ist. Nun, wenn Sie logische Operatoren in JavaScript verwenden, ist alles außer '' (eine leere Zeichenfolge), 0
, false
, null
oder undefined
wahr. Eine gesonderte Prüfung ist nicht erforderlich.
searchPicture() { //Default state this.setState({loading: true, error: null, imgUrl: null}); axios.get('https://www.reddit.com/r/pics/search.json', { params: { //the get param map restrict_sr: 'on', //search only /r/pics limit: 1, //limit to one search item sort: 'new', //sort by creation date q: this.state.text //our search query } }).then(response => { //promise is resolved and 'then' block is triggered //set state with new values this.setState({ imgUrl: response.data.data.children[0] .data.preview.images[0].source.url, error: null, loading: false }) }).catch(error => {//Some error occurred //set error this.setState({error: error.message, loading: false, imgUrl: null}) }) }
Auf geht's. Die Anwendung sollte jetzt wie erwartet funktionieren. Geben Sie einen Suchbegriff ein und drücken Sie die Eingabetaste.

Da unsere Anwendung auch bereit ist, ActivityIndicator
und Fehler zu rendern, müssen wir nach der Image
Komponente etwas mehr Code hinzufügen:
{ //Separate method this.renderProgress() } {/* Render error Text component if this.state.error is not equal to null */} { this.state.error && <Text style={{margin: 16, color: 'red'}}> {this.state.error} </Text> }
Sie können Renderkomponenten auch außerhalb der Methode main render()
verschieben:
renderProgress() { //If this.state.loading is true //return View containing a progressbar //View takes style array if (this.state.loading === true) { return ( <View style={ [styles.containerStyle, {justifyContent: 'center'}]}> <ActivityIndicator color='#e57373'/> </View> ); } }
Alles, was übrig bleibt, sind Stile. Platzieren Sie diese außerhalb der App
-Klasse.
const styles = StyleSheet.create({ containerStyle: { flexDirection: 'column', flex: 1, //Since React Native is cross platform //let's handle both platforms. //Add top margin to fix status bar overlap marginTop: Platform.OS === 'ios' ? 20 : 0, }, textInputStyle: { marginLeft: 16, marginRight: 16, height: Platform.OS === 'ios' ? 30 : undefined } });
Wir können jetzt einige weitere Optimierungen hinzufügen, wie das automatische Öffnen der Soft-Tastatur, wenn die Anwendung gestartet wird.
Bitte beachten Sie, dass es einen einfacheren Weg gibt, TextInput
automatisch zu fokussieren ( autoFocus={true} prop
), aber für dieses Beispiel werden wir ihn nicht verwenden.
Verweis auf TextInput
mit prop hinzufügen:
ref={ref => this.searchInput = ref}
Und überschreiben Sie die Lebenszyklusmethode componentDidMount()
wie folgt:
componentDidMount(){ this.searchInput.focus(); }
Laden Sie die App neu und die Tastatur wird automatisch für uns geöffnet.
Komponentenlebenszyklusmethoden
Wir haben bereits eine Komponente erstellt, aber lassen Sie uns die Lebensdauer einer Komponente durchgehen.
Hier ist der Lebenszyklusablauf von React:
-
constructor()
- Der Konstruktor wird immer aufgerufen, wenn die Anwendung gestartet wird -
static _getDerivedStateFromProps_(props, state)
– Wird vor dem Rendern und nach dem Update aufgerufen. Gibt ein Objekt zum Aktualisieren des Zustands zurück. Geben Sie null zurück, um nichts zu aktualisieren. -
render()
- Render ist für jede React-Komponentenklasse erforderlich. Es wird zum Rendern von View verwendet. -
componentDidMount()
– Wird aufgerufen, nachdem die Komponente gerendert und in den Ansichtsbaum eingebunden wurde. -
shouldComponentUpdate(nextProps, nextState)
– Wird aufgerufen, nachdem sich der Status oder die Requisiten geändert haben. Die Rückgabe ist nach jeder Zustandsaktualisierung standardmäßig wahr. Ruftrender()
auf, wenn true zurückgegeben wird. -
getSnapshotBeforeUpdate(prevProps, prevState)
– Wird unmittelbar vor dem Festschreiben der gerenderten Ausgabe aufgerufen. -
componentDidUpdate(prevProps, prevState, snapshot)
– Wird nach dem Rendern eines neuen Updates aufgerufen. Es wird nicht nach dem erstenrender()
aufgerufen. -
componentWillUnmount()
– Wird aufgerufen, kurz bevor die Komponente ausgehängt und zerstört wird.
Wiederverwendbare Komponenten
Wir müssen oft wiederverwendbare Komponenten erstellen, wenn wir an dem Projekt arbeiten. Es gibt zwei Möglichkeiten, eine Komponente zu erstellen:
- Erstellen einer Klasse, die
React.Component
erweitert. Diese Methode sollte verwendet werden, wenn wir Lebenszyklusmethoden benötigen. - Durch Schreiben einer Funktion, die View für eine einfachere Syntax zurückgibt.
Da wir bereits Komponentenklassen erstellt haben, erstellen wir eine Funktion für diese Instanz.
Angenommen, wir brauchen ein Analogon zu <CardView>
. Erstellen Sie einen „gemeinsamen“ Ordner im Verzeichnis ./src
.
Erstellen Sie CardView.js
.
import React from "react"; import {View} from "react-native"; export default CardView = (props) => { return ( //Style will be merged from default containerStyle //and props.style. props.style attributes will override //values if parameters are same. <View style={{...styles.containerStyle, ...props.style}}> {/* props.children contain subviews add this line if the component is container */} {props.children} </View> ); }; const styles = { containerStyle: { borderRadius: 4, margin: 5, padding: 5, elevation: 5, shadowColor: 'black', shadowRadius: 5, shadowOpacity: 0.5, shadowOffset: {width: 0, height: 3}, backgroundColor: 'white' } };
LoginForm
mit unserem neuen CardView
Layout:
import React from "react"; import {TextInput, Platform, Button, StyleSheet} from "react-native"; import CardView from "../common/components/CardView"; export default class LoginForm extends React._Component _{ render() { return ( //Override default style <CardView style={{ borderRadius: 4, backgroundColor: '#fff' }}> <TextInput placeholder="Email" style={styles.textInputStyle}/> <TextInput placeholder="Password" style={styles.textInputStyle} secureTextEntry={true}/> <Button color="#841584" title="Login" onPress={() => console.log("onLoginPress")} buttonStyle={styles.buttonStyle}/> </CardView> ); } } const styles = StyleSheet.create({ buttonStyle: { elevation: 5, height: 40 }, textInputStyle: { padding: 10, //Additional params to make //iOS inputs prettier ...Platform.select({ ios: { borderRadius: 2, marginTop: 5, backgroundColor: '#eeeeee' } }) } });
Importieren Sie die LoginForm
-Klasse in die App
-Klasse und umschließen Sie sie mit View
<View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>
Wenn Sie die Parameter in den Stilen anpassen, können Sie etwas erhalten, das viel schöner aussieht.
Navigation
Die Navigation zu verschiedenen Szenen ist ein wesentlicher Bestandteil für die meisten Anwendungen. Wir werden eine Reddit /r/pics-Browser-App erstellen.
Das Erstellen einer Navigation in React Native ist ziemlich einfach.
Voraussetzungen
- React
react-navigation
mityarn
odernpm
installieren -
axios
mityarn
odernpm
installieren
Beginnen wir damit, zwei verschiedene Komponenten zu erstellen.
Hinweis: Der größte Teil des folgenden Codes sollte Ihnen bereits bekannt sein. Ich werde die ganze Klasse einfügen.
PictureList.js:
import React from 'react'; import { ActivityIndicator, FlatList, Image, Text, TouchableHighlight, View } from "react-native"; import axios from "axios"; import CardView from "../common/CardView"; export default class PictureList extends React.Component { state = {loading: true, error: null, posts: null}; componentDidMount() { axios.get('https://www.reddit.com/r/pics.json') .then(response => { this.setState({ posts: response.data.data.children, loading: false }) }).catch(error => { this.setState({ error: error.message, loading: false }) }) } render() { return ( <View style={{flex: 1, justifyContent: 'center'}}> // FlatList ~ ListView // data - DataSource for the List // renderItem - function returns View item // keyExtractor - Unique id for items {this.state.posts && <FlatList data={this.state.posts} renderItem={this.renderItem.bind(this)} keyExtractor={(item) => (item.data.id + '')}/>} {this.state.loading && <ActivityIndicator size="large" color="#f4511e"/>} </View> ); } navigateToPicture(title, url) { this.props.navigation.navigate('PicturePreview', { 'title': title, 'url': url }) } renderItem(item) { //Destructuring values from item //Read more 'ES6 destructuring' const {data} = item.item; const {title} = data; const {url} = data.preview.images[0].source; return ( //Clickable view <TouchableHighlight onPress={() => this.navigateToPicture(title, url)}> {/Reusing our CardView/} <CardView> <Image style={{height: 150}} source={{uri: url}}/> <Text style={{padding: 5}}>{title}</Text> </CardView> </TouchableHighlight> ) } }
PicturePreview.js
:
import React from 'react'; import {Image} from "react-native"; export default class PicturePreview extends React.Component { //Destructure navigation //Set title to header static _navigationOptions = ({navigation}) => ({ title: navigation.state.params.title }); render() { const {url} = this.props.navigation.state.params; return (<Image style={{flex: 1}} source={{uri: url}}/>) } }
Die navigationOptions
werden automatisch von React-Navigation aufgerufen.
Kommen wir nun zu App.js
Hinweis: Es gibt viele Navigationstypen in React-Navigation. Heute konzentrieren wir uns auf StackNavigation
. Weitere Informationen finden Sie auf der offiziellen Website.
import React from 'react'; import {createStackNavigator} from "react-navigation"; import PictureList from "./components/PictureList"; import PicturePreview from "./components/PicturePreview"; export default class App extends React.Component { render() { return ( <Router/> ); } } //Customize the header_ const NavigationOptions = { headerTintColor: '#fff', headerStyle: { backgroundColor: '#f4511e', } }; //Create the router. const Router = createStackNavigator({ //Name the screen 'PictureList': { //Link the Component screen: PictureList, //Additional navigation options navigationOptions: { title: '/r/pics Browser', ...NavigationOptions } }, 'PicturePreview': { screen: PicturePreview, navigationOptions: NavigationOptions } }, { //Root initialRouterName: 'PictureList' } );
Wie Sie sehen, müssen wir lediglich einen Navigationsrouter erstellen und ihn von der App rendern lassen. Wenn alles gut gelaufen ist, haben wir eine funktionierende Reddit /r/pics-Browser-App.
Android:
iOS:
React Native ist erstaunlich!
Seit ich mit dem Programmieren angefangen habe, habe ich rein mobile Entwicklungserfahrungen gesammelt. Aber jetzt kann ich mit React für so ziemlich alles programmieren: Mobil, Desktop und Web.
Wenn Sie sich entscheiden, Ihre nächste erstaunliche Anwendung mit React Native zu entwickeln, werden Sie feststellen, dass es hier und da seine Macken und einige Fehler hat, aber React Native ist sehr funktional und ideal für die meisten Projekte.