Immergiti in React Native per lo sviluppo Android
Pubblicato: 2022-03-11Qualche anno fa, un mio collega mi parlò di React Native. Ero molto scettico. Ho sostenuto che è solo un altro framework multipiattaforma che non funzionerà mai nella vita reale – non sapevo quanto mi sbagliassi.
Passarono gli anni e le abilità React Native divennero molto richieste. Dato che era da un po' che imparavo qualcosa di nuovo, ho pensato perché non provarci? Oggi sono un grande sostenitore di React Native.
Contro:
- Non puoi più utilizzare Android Studio
- React Native non può essere utilizzato per ogni applicazione o funzionalità
- React Native è un nuovo framework e gli aggiornamenti possono avere un effetto negativo sulla tua attuale base di codice
- JavaScript non è un linguaggio rigorosamente tipizzato
- React Native richiede l'esecuzione di un motore JavaScript, che potrebbe renderlo meno performante
Professionisti:
- Facile da imparare
- Una base di codice condivisa tra le app Android e iOS, con solo piccole modifiche necessarie per abbinare le esperienze della piattaforma
- Ricarica dal vivo e a caldo, il che significa che non ci sono più tempi di costruzione infiniti
- Componenti nativi per entrambe le piattaforme
- Migliorando costantemente
- Comunità in crescita attiva
- Numero enorme di biblioteche
- Expo elimina la necessità di possedere un Mac da sviluppare per iOS
- Riduzione delle risorse di manodopera: anche se potresti aver ancora bisogno di un po' di sviluppo nativo per Android/iOS, sarà raro.
Posso andare avanti all'infinito, ma fermiamoci qui e passiamo all'argomento di questo post del blog. In questo post, creerò quattro app Android basate su React Native:
- Un contatore di base con pulsanti per incrementare e decrementare il contatore
- Un'app per cercare il subreddit r/pics
- Una pagina di accesso generica
- Un'app per navigare nel subreddit r/pics
IDE
Come accennato in precedenza, non è possibile utilizzare Android Studio per lo sviluppo di React Native. Abbiamo bisogno di un sostituto. React Native può essere sviluppato probabilmente in qualsiasi moderno editor di testo disponibile (Atom, VS Code, Sublime Text, Brackets, ecc.) ma dal momento che stiamo arrivando con l'esperienza di Android Studio, il mio preferito è WebStorm che è costruito dalla stessa azienda. Sebbene WebStorm sia un'applicazione a pagamento (129 $ all'anno), puoi installarne la versione Early Access. La build EAP di WebStorm è gratuita e abbastanza stabile. Se preferisci un editor completamente gratuito, scegli VS Code. Microsoft ha persino sviluppato un fantastico plug-in React Native per questo e funziona molto bene.
Creazione di un nuovo progetto
Prerequisiti: Android SDK, Node e React Native installati sul tuo computer.
Esistono due modi per creare un nuovo progetto React Native.
- Il modo convenzionale. O con WebStorm GUI o con il comando da terminale:
react-native init AwesomeToptalProject
- Modo più semplice "Crea un'app React Native".
create-react-native-app AwesomeToptalProject
Se usi create-react-native-app
, il progetto creato verrà avviato con expo. Non entrerò nei dettagli, ma in pratica significa che non è necessario che Xcode sia installato per eseguire l'app su iOS. È anche più facile avere il cliente sempre aggiornato attraverso le funzionalità di expo.io e alcune altre funzionalità. Ma non puoi aggiungere codice nativo. Pertanto, se stai sviluppando una funzionalità specifica, potrebbe essere necessario espellere un'app da expo e utilizzare invece un normale progetto React Native.
Userò il primo metodo.
Gestiamo il progetto. Innanzitutto, apri un emulatore o collega il dispositivo. Se hai creato il progetto con WebStorm GUI, tutto ciò che devi fare è scegliere una configurazione. Nell'angolo in alto a destra di WebStorm, fai clic sull'elenco a discesa a sinistra del pulsante Esegui, scegli Android e fai clic su Esegui o Debug. Se hai creato il progetto con Terminal, puoi aggiungere una nuova configurazione React Native o eseguirla utilizzando Terminal:
cd AwesomeToptalProject react-native run-android
Se tutto è andato bene, verrai accolto con la seguente schermata:

Struttura e configurazione di base
Gli elementi degni di nota all'interno del progetto sono:
- Android - Progetto Android Studio preconfigurato con supporto React Native.
- ios - Progetto Xcode preconfigurato con supporto React Native.
- node_modules - Una cartella contenente il framework React Native e altre librerie Javascript.
- index.js - Un punto di ingresso per la nostra app.
- App.js - Componente iniziale caricato.
Creiamo una cartella "src" all'interno della radice del progetto e spostiamo App.js lì. Dovrai aggiornare le importazioni di index.js in modo che corrispondano alla nuova posizione di App.js.
import App from './src/App';
Elimina tutto all'interno di App.js e incolla questo codice:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }
Il codice che abbiamo incollato è piuttosto semplice. Abbiamo creato App
di classe (figlio di React.Component
) che sovrascrive il metodo render()
e restituisce il componente Text
. React.Component
è la classe base per la creazione dell'interfaccia utente utilizzando JSX. Il modificatore export default
rende la classe public
.
Ora siamo pronti per iniziare a progettare il nostro layout.
Disposizione con Flexbox
Flexbox
è simile a LinearLayout
, ma Flexbox
va ben oltre le capacità di LinearLayout
.
Questo frammento di 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>
Rende questo layout:
Mentre questo 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>
Rende questo:
Il codice JSX sembra familiare, eh?! Creiamo un "dizionario" (o un cheatsheet) per i layout che hanno un aspetto simile in JSX e Android XML.
Si prega di notare che le funzionalità non sono necessariamente uguali. Sto cercando di aiutare i neofiti di React Native a cogliere l'idea del sistema di layout in React Native. Si prega di fare riferimento alla guida ufficiale per informazioni dettagliate.
Considera questa proprietà JSX:
flex: 1
È equivalente a questo:
android:layout_width="match_parent" android:layout_height="match_parent"
Questo frammento di 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>
E questo 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>
Entrambi generano questo output:
Allo stesso modo, questo 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>
E questo 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>
Genera questo:
Per ottenere la posizione corretta all'interno del contenitore, useremo più comunemente una combinazione di flexDirection
, alignItems
e justifyContent
.
questo 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>
E questo 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>
Produrrà questo layout:
questo 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>
E questo 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>
Produrrà questo layout:
questo 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>
E questo 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>
Produrrà questo layout:
questo 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>
e questo 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>
Produrrà questo layout:
Lezione da imparare: se abbiamo flexDirection: row',
alignItems works on Y axis and
justifyContent works on X axis. Everything is mirrored for
works on X axis. Everything is mirrored for
flexDirection: column' - justifyContent
influisce sull'asse Y e alignItems
influisce sull'asse Y.
giustificaContenuto: 'flex-start' | gravità="inizio|sinistra" |
alignItems: 'flex-start' | gravità="inizio|sinistra" |
giustificaContenuto: 'flex-end' | gravità="fine|destra" |
alignItems: 'flex-end' | gravità="fine|destra" |
Provate voi stessi. Imposta il valore justifyContent
su space-around
, space-between
e space-evenly
.
Gestione dello Stato
Per aggiornare lo stato dell'applicazione, utilizzerai la variabile di state
di React. Ogni volta che state
viene aggiornato, viene invocato render()
.
Copia il codice qui sotto nella tua 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}); } }

Se fai clic sui pulsanti DECREMENT e INCREMENT, vedrai che il testo viene aggiornato automaticamente per te. Non è necessario utilizzare esplicitamente textView.setText("Value " + number)
.

La funzionalità di stato è utile per diversi motivi:
- Facilità di ottenere il valore: sai sempre dove e come ottenere il valore per una variabile specifica.
- I dati non sono vincolati a widget specifici.
- Avere più widget dipendenti dalla modifica del valore comune.
Creazione di un'app di ricerca per /r/pics
Ora che abbiamo le nozioni di base, creiamo qualcosa di un po' più complesso: un'app di ricerca per /r/pics. Reddit fornisce un semplice endpoint API JSON, quindi non dovremo eseguire missioni secondarie per ottenere l'autenticazione affinché funzioni correttamente.
React Native fornisce un'API di recupero integrata. Poiché la maggior parte di noi è probabilmente abituata a Retrofit e alla sua facilità d'uso, utilizzeremo axios . È possibile installare axios tramite un comando da terminale
usando yarn
(il mio metodo preferito):
yarn add axios
o usando npm
:
npm install axios
Importazioni:
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
Crea la classe:
export default class App extends React.Component { }
Per inizializzare lo stato. Avremo bisogno di:
- caricamento - Per mostrare una barra di avanzamento.
- errore - Per mostrare se si è verificato un errore durante la richiesta dell'API REST.
- imgUrl - Per visualizzare in anteprima l'immagine cercata.
- testo - query di ricerca.
state = {text: '', loading: false, error: null, imgUrl: null};
Aggiungi il codice JSX. Abbiamo un layout verticale con i TextInput
e Image
.
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> ); }
Cose nuove:
onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }
Il primo metodo funziona in modo simile a EditText
con il componente TextWatcher
. Siamo onesti, è molto più bello in React Native.
Il secondo metodo viene richiamato quando viene premuto il tasto Invio sulla tastiera ( et.OnEditorActionListener
) dopo che ha attivato searchPicture()
.
L'immagine viene visualizzata quando imgUrl
non è nullo o non definito poiché l'operatore '&&' non verifica un secondo argomento se il primo è già falso.
Ti starai chiedendo perché this.state.imgUrl
è falso. Ebbene, quando si utilizzano operatori logici in JavaScript, qualsiasi cosa tranne '' (una stringa vuota), 0
, false
, null
o undefined
è true. Non c'è bisogno di un controllo specifico.
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}) }) }
Eccoci qui. L'applicazione dovrebbe funzionare come previsto ora. Immettere una stringa di ricerca e premere Invio.

Poiché la nostra applicazione è pronta anche per il rendering di ActivityIndicator
ed errori, dobbiamo aggiungere altro codice dopo il componente Image
:
{ //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> }
Puoi anche spostare i componenti di rendering al di fuori del metodo render()
principale:
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> ); } }
Tutto ciò che resta sono gli stili. Mettili al di fuori della classe App
.
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 } });
Ora possiamo aggiungere altre modifiche come l'apertura automatica della tastiera software all'avvio dell'applicazione.
Tieni presente che esiste un modo più semplice per mettere a fuoco automaticamente TextInput
( autoFocus={true} prop
), ma per il bene di questo esempio, non lo useremo.
Aggiungi riferimento a TextInput
con prop:
ref={ref => this.searchInput = ref}
E sovrascrivi il metodo del ciclo di vita componentDidMount()
in questo modo:
componentDidMount(){ this.searchInput.focus(); }
Ricarica l'app e la tastiera si aprirà automaticamente per noi.
Metodi del ciclo di vita dei componenti
Abbiamo già creato un componente, ma analizziamo la vita di un componente.
Ecco il flusso del ciclo di vita di React:
-
constructor()
- Il costruttore viene sempre chiamato all'avvio dell'applicazione -
static _getDerivedStateFromProps_(props, state)
- Chiamato prima del rendering e dopo l'aggiornamento. Restituisce l'oggetto per l'aggiornamento dello stato. Restituisci null per non aggiornare nulla. -
render()
- Il rendering è richiesto per ogni classe React Component. Viene utilizzato per il rendering di View. -
componentDidMount()
- Viene richiamato dopo che il componente è stato renderizzato e montato nell'albero della vista. -
shouldComponentUpdate(nextProps, nextState)
- Chiamato dopo la modifica dello stato o degli oggetti di scena. Il valore predefinito è true dopo ogni aggiornamento dello stato. Richiamarender()
se restituisce true. -
getSnapshotBeforeUpdate(prevProps, prevState)
- Chiamato appena prima del commit dell'output di rendering. -
componentDidUpdate(prevProps, prevState, snapshot)
- Chiamato dopo il rendering del nuovo aggiornamento. Non viene chiamato dopo il primorender()
. -
componentWillUnmount()
- Chiamato appena prima che il componente venga smontato e distrutto.
Componenti riutilizzabili
Spesso abbiamo bisogno di creare componenti riutilizzabili quando lavoriamo al progetto. Esistono due modi per creare un componente:
- Creazione di una classe che estende
React.Component
. Questo metodo dovrebbe essere utilizzato se abbiamo bisogno di metodi del ciclo di vita. - Scrivendo una funzione che restituisce View per una sintassi più semplice.
Poiché abbiamo già creato classi Component, creiamo una funzione per questa istanza.
Supponiamo di aver bisogno di un analogo per <CardView>
. Crea una cartella "comune" nella directory ./src
.
Crea 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
utilizzando il nostro nuovo layout CardView
:
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' } }) } });
Importa la classe LoginForm
nella classe App
e avvolgila con View
<View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>
Se modifichi i parametri negli stili, puoi ottenere qualcosa che sembra molto più bello.
Navigazione
La navigazione in diverse scene è una parte essenziale per la maggior parte delle applicazioni. Creeremo un'app browser Reddit /r/pics.
Creare la navigazione in React Native è abbastanza semplice.
Prerequisiti
- Installa
react-navigation
reattiva conyarn
onpm
- Installa
axios
conyarn
onpm
Iniziamo creando due diversi componenti.
Nota: la maggior parte del codice seguente dovrebbe già esserti familiare. Incollerò l'intera classe.
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}}/>) } }
Le opzioni di navigationOptions
verranno automaticamente richiamate da React-Navigation.
Ora passiamo a App.js
Nota: ci sono molti tipi di navigazione in React-Navigation. Oggi ci concentreremo su StackNavigation
. Si prega di fare riferimento al sito ufficiale per informazioni dettagliate.
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' } );
Come puoi vedere, tutto ciò che dobbiamo fare è creare un router di navigazione e fare in modo che l' app lo renda. Se tutto è andato bene, avremo un'app browser Reddit /r/pics funzionante.
Android:
iOS:
React Native è incredibile!
Da quando ho iniziato a programmare, ho avuto esperienze di sviluppo puramente mobile. Ma ora posso programmare praticamente qualsiasi cosa con React: mobile, desktop e web.
Se decidi di iniziare a sviluppare la tua prossima fantastica applicazione usando React Native, scoprirai che ha le sue stranezze e alcuni bug qua e là, ma React Native è molto funzionale e ideale per la maggior parte dei progetti.