Păstrați-vă în React Native pentru dezvoltarea Android
Publicat: 2022-03-11Acum câțiva ani, un coleg de-al meu mi-a povestit despre React Native. Eram foarte sceptic. Am susținut că este doar un alt cadru multiplatform care nu va funcționa niciodată în viața reală – nu știam cât de greșit am greșit.
Anii au trecut și abilitățile React Native au devenit foarte solicitate. De vreme ce am învățat ceva nou, m-am gândit de ce să nu încerc? Astăzi, sunt un mare avocat al React Native.
Contra:
- Nu mai poți folosi Android Studio
- React Native nu poate fi utilizat pentru fiecare aplicație sau caracteristică
- React Native este un cadru nou, iar actualizările pot avea un efect negativ asupra bazei de cod curente
- JavaScript nu este un limbaj strict scris
- React Native necesită un motor JavaScript pentru a rula, ceea ce îl poate face mai puțin performant
Pro:
- Usor de invatat
- O bază de cod partajată între aplicațiile Android și iOS, cu doar modificări minore necesare pentru a se potrivi cu experiențele platformei
- Reîncărcare live și la cald, ceea ce înseamnă că nu mai există timpi infiniti de construcție
- Componente native pentru ambele platforme
- În continuă îmbunătățire
- Comunitate în creștere activă
- Număr mare de biblioteci
- Expo elimină necesitatea de a deține un Mac pentru a dezvolta pentru iOS
- Reducerea resurselor de muncă — deși s-ar putea să mai aveți nevoie de o dezvoltare nativă Android/iOS, aceasta va fi rar.
Pot continua și mai departe, dar hai să ne oprim aici și să trecem la subiectul acestei postări pe blog. În această postare, voi crea patru aplicații Android bazate pe React Native:
- Un contor de bază cu butoane pentru a crește și a reduce contorul
- O aplicație pentru a căuta subreddit-ul r/pics
- O pagină de autentificare generică
- O aplicație pentru a răsfoi subreddit-ul r/pics
IDE
După cum am menționat mai sus, nu putem folosi Android Studio pentru dezvoltarea React Native. Avem nevoie de un înlocuitor. React Native poate fi dezvoltat probabil în orice editor de text modern disponibil (Atom, VS Code, Sublime Text, Brackets, etc.), dar din moment ce venim cu experiența Android Studio preferatul meu este WebStorm, care este construit de aceeași companie. Deși WebStorm este o aplicație plătită (129 USD pe an), puteți instala versiunea Early Access a acesteia. EAP build a WebStorm este gratuită și destul de stabilă. Dacă preferați un editor care este complet gratuit, alegeți VS Code. Microsoft a dezvoltat chiar un plugin uimitor React Native pentru el și funcționează foarte bine.
Crearea unui nou proiect
Cerințe preliminare: Android SDK, Node și React Native instalate pe computer.
Există două moduri de a crea un nou proiect React Native.
- Modul convențional. Fie cu WebStorm GUI, fie cu comanda terminalului:
react-native init AwesomeToptalProject
- Mod mai simplu „Creați aplicația React Native”.
create-react-native-app AwesomeToptalProject
Dacă utilizați create-react-native-app
, proiectul creat va fi bootstrap cu expo. Nu voi intra în detalii, dar practic înseamnă că nu trebuie să aveți Xcode instalat pentru a rula aplicația pe iOS. Este, de asemenea, mai ușor să ai clientul mereu la zi prin funcționalitatea expo.io și alte caracteristici. Dar nu puteți adăuga cod nativ. Astfel, dacă dezvoltați o funcție specifică, poate fi necesar să scoateți o aplicație din expoziție și să utilizați în schimb un proiect obișnuit React Native.
Voi folosi prima metodă.
Să rulăm proiectul. Mai întâi, deschideți un emulator sau conectați dispozitivul. Dacă ați creat proiectul cu WebStorm GUI, tot ce trebuie să faceți este să alegeți o configurație. În colțul din dreapta sus al WebStorm, faceți clic pe meniul drop-down din stânga butonului Run, alegeți Android și faceți clic pe Run sau Debug. Dacă ați creat proiectul cu Terminal, puteți fie să adăugați o nouă configurație React Native, fie să o rulați folosind Terminal:
cd AwesomeToptalProject react-native run-android
Dacă totul a mers bine, veți fi întâmpinat cu următorul ecran:

Structură și setare de bază
Elementele notabile din cadrul proiectului sunt:
- android - proiect Android Studio preconfigurat cu suport React Native.
- ios - proiect Xcode preconfigurat cu suport React Native.
- node_modules - Un folder care conține framework-ul React Native și alte biblioteci Javascript.
- index.js - Un punct de intrare pentru aplicația noastră.
- App.js - Componenta inițială încărcată.
Să creăm un folder „src” în rădăcina proiectului și să mutăm App.js acolo. Va trebui să actualizați importurile index.js pentru a se potrivi cu noua locație App.js.
import App from './src/App';
Ștergeți totul din App.js și inserați acest cod:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }
Codul pe care l-am lipit este destul de simplu. Am creat o clasă App
(copilul React.Component
) care suprascrie metoda render()
și returnează componenta Text
. React.Component
este clasa de bază pentru construirea UI folosind JSX. Modificatorul export default
face clasa public
.
Acum suntem gata să începem proiectarea aspectului nostru.
Aspect cu Flexbox
Flexbox
este similar cu LinearLayout
, dar Flexbox
depășește cu mult abilitățile lui LinearLayout
.
Acest fragment de 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>
Redă acest aspect:
În timp ce acest 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>
Redă asta:
Codul JSX pare familiar, nu?! Să creăm un „dicționar” (sau un cheatsheet) pentru machete care să arate similar în JSX și Android XML.
Vă rugăm să rețineți că funcționalitățile nu sunt neapărat egale. Încerc să îi ajut pe începătorii React Native să înțeleagă ideea sistemului de aspect în React Native. Vă rugăm să consultați ghidul oficial pentru informații detaliate.
Luați în considerare această proprietate JSX:
flex: 1
Este echivalent cu asta:
android:layout_width="match_parent" android:layout_height="match_parent"
Acest fragment de 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>
Și acest 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>
Ambele generează această ieșire:
În mod similar, acest 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>
Și acest 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ți asta:
Pentru a obține poziția corectă în interiorul containerului, cel mai frecvent vom folosi o combinație de flexDirection
, alignItems
și justifyContent
.
Acest 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>
Și acest 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>
Va produce acest aspect:
Acest 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>
Și acest 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>
Va produce acest aspect:
Acest 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>
Și acest 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>
Va produce acest aspect:
Acest 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>
și acest 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>
Va produce acest aspect:
Lecție de învățat: dacă avem 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
afectează axa Y și alignItems
afectează axa Y.
justifyContent: „flex-start” | gravity="start|left" |
alignItems: 'flex-start' | gravity="start|left" |
justifyContent: „flex-end” | gravitate="end|dreapta" |
alignItems: 'flex-end' | gravitate="end|dreapta" |
Incearca-l tu insuti. Setați valoarea justifyContent
la space-around
, space-between
și space-evenly
.
Managementul Statului
Pentru a actualiza starea aplicației, veți folosi variabila de state
a lui React. Ori de câte ori state
este actualizată, render()
este invocat.
Copiați codul de mai jos în aplicația dvs.:
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}); } }

Dacă faceți clic pe butoanele DECREȘARE și INCREMENTARE, veți vedea că textul este actualizat automat pentru dvs. Nu este nevoie să utilizați în mod explicit textView.setText("Value " + number)
.

Funcționalitatea de stat este utilă din mai multe motive:
- Ușurință în obținerea valorii — știți întotdeauna unde și cum să obțineți valoarea pentru o anumită variabilă.
- Datele nu sunt legate de anumite widget-uri.
- Având mai multe widget-uri în funcție de modificarea valorii comune.
Crearea unei aplicații de căutare pentru /r/pics
Acum că ne înțelegem elementele fundamentale, să creăm ceva mai complex: o aplicație de căutare pentru /r/pics. Reddit oferă un punct final JSON API simplu, așa că nu va trebui să facem misiuni secundare pentru a obține autentificare pentru ca acesta să funcționeze corect.
React Native oferă un API Fetch încorporat. Deoarece majoritatea dintre noi sunt probabil obișnuiți cu Retrofit și ușurința sa de utilizare, vom folosi axios . Puteți instala axios printr-o comandă de terminal
folosind yarn
(metoda mea preferată):
yarn add axios
sau folosind npm
:
npm install axios
Importuri:
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ți clasa:
export default class App extends React.Component { }
Pentru a inițializa starea. Vom avea nevoie de:
- încărcare - Pentru afișarea unei bare de progres.
- eroare - Pentru a arăta dacă a apărut o eroare la efectuarea unei solicitări API REST.
- imgUrl - Pentru a previzualiza imaginea căutată.
- text - interogare de căutare.
state = {text: '', loading: false, error: null, imgUrl: null};
Adăugați codul JSX. Avem un aspect vertical cu componente TextInput
și 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> ); }
Lucruri noi:
onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }
Prima metodă face o activitate similară cu EditText
cu componenta TextWatcher
. Să fim sinceri, este mult mai frumos în React Native.
A doua metodă este invocată atunci când tasta return este apăsată pe tastatură ( et.OnEditorActionListener
) după ce declanșează searchPicture()
.
Imaginea este redată atunci când imgUrl
nu este nulă sau nedefinită, deoarece operatorul „&&” nu verifică un al doilea argument dacă primul este deja fals.
S-ar putea să vă întrebați de ce this.state.imgUrl
este fals. Ei bine, atunci când utilizați operatori logici în JavaScript, orice cu excepția „” (un șir gol), 0
, false
, null
sau undefined
este adevărat. Nu este nevoie de un control specific.
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}) }) }
Începem. Aplicația ar trebui să funcționeze conform așteptărilor acum. Introduceți un șir de căutare și apăsați Retur.

Deoarece aplicația noastră este, de asemenea, pregătită pentru a reda ActivityIndicator
și erori, trebuie să mai adăugăm ceva cod după componenta 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> }
De asemenea, puteți muta componentele de randare în afara metodei principale de render()
:
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> ); } }
Tot ce a mai rămas sunt stiluri. Pune-le în afara clasei 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 } });
Acum putem adăuga câteva modificări, cum ar fi deschiderea automată a tastaturii soft atunci când aplicația este lansată.
Vă rugăm să rețineți că există o modalitate mai ușoară de a face TextInput
să se concentreze automat ( autoFocus={true} prop
), dar de dragul acestui exemplu, nu îl vom folosi.
Adăugați referință la TextInput
cu prop:
ref={ref => this.searchInput = ref}
Și suprascrieți metoda ciclului de viață componentDidMount()
astfel:
componentDidMount(){ this.searchInput.focus(); }
Reîncărcați aplicația și tastatura se deschide automat pentru noi.
Metode ale ciclului de viață al componentelor
Am creat deja o componentă, dar să trecem prin durata de viață a unei componente.
Iată fluxul ciclului de viață al lui React:
-
constructor()
- Constructorul este întotdeauna apelat când aplicația este pornită -
static _getDerivedStateFromProps_(props, state)
- Apelat înainte de randare și după actualizare. Returnează obiectul pentru actualizarea stării. Returnează null pentru a nu actualiza nimic. -
render()
- Redarea este necesară pentru fiecare clasă React Component. Este folosit pentru a reda View. -
componentDidMount()
- Este invocat după ce componenta este randată și montată în arborele de vizualizare. -
shouldComponentUpdate(nextProps, nextState)
- Apelat după schimbarea stării sau a elementelor de recuzită. Revenirea este implicită la true după fiecare actualizare de stare. Invocărender()
dacă returnează adevărat. -
getSnapshotBeforeUpdate(prevProps, prevState)
- Apelat chiar înainte ca rezultatul redat să fie comis. -
componentDidUpdate(prevProps, prevState, snapshot)
- Apelat după ce a redat o nouă actualizare. Nu este apelat după primulrender()
. -
componentWillUnmount()
- Apelat chiar înainte ca componenta să fie demontată și distrusă.
Componente reutilizabile
De multe ori trebuie să creăm componente reutilizabile atunci când lucrăm la proiect. Există două moduri de a crea o componentă:
- Crearea unei clase care extinde
React.Component
. Această metodă ar trebui folosită dacă avem nevoie de metode de ciclu de viață. - Prin scrierea unei funcții care returnează View pentru o sintaxă mai simplă.
Deoarece am creat deja clase de componente, să creăm o funcție pentru această instanță.
Să presupunem că avem nevoie de un analog pentru <CardView>
. Creați un folder „comun” în directorul ./src
.
Creați 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
folosind noul nostru aspect 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ți clasa LoginForm
în clasa App
și împachetați-o cu View
<View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>
Dacă modificați parametrii în stiluri, puteți obține ceva care arată mult mai frumos.
Navigare
Navigarea către diferite scene este o parte esențială pentru majoritatea aplicațiilor. Vom crea o aplicație de browser Reddit /r/pics.
Crearea navigației în React Native este destul de ușoară.
Cerințe preliminare
- Instalați
react-navigation
cuyarn
saunpm
- Instalați
axios
cuyarn
saunpm
Să începem prin a crea două componente diferite.
Notă: majoritatea codului de mai jos ar trebui să vă fie deja familiar. Voi lipi toată clasa.
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}}/>) } }
Opțiunile de navigationOptions
vor fi invocate automat de React-Navigation.
Acum să trecem la App.js
Notă: Există multe tipuri de navigare în React-Navigation. Astăzi, ne vom concentra pe StackNavigation
. Vă rugăm să consultați site-ul oficial pentru informații detaliate.
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' } );
După cum puteți vedea, tot ce trebuie să facem este să creăm un router de navigare și să facem ca aplicația să-l redea. Dacă totul a mers bine, vom avea o aplicație funcțională de browser Reddit /r/pics.
Android:
iOS:
React Native este uimitor!
De când am început să programez, am avut experiențe de dezvoltare pur mobilă. Dar acum pot codifica pentru aproape orice cu React: mobil, desktop și web.
Dacă decideți să începeți să vă dezvoltați următoarea aplicație uimitoare folosind React Native, veți descoperi că are ciudateniile sale și unele erori pe alocuri, dar React Native este foarte funcțional și ideal pentru majoritatea proiectelor.