Android Geliştirme için React Native'e dalın
Yayınlanan: 2022-03-11Birkaç yıl önce bir iş arkadaşım bana React Native'den bahsetti. çok şüpheciydim. Bunun gerçek hayatta asla çalışmayacak başka bir platformlar arası çerçeve olduğunu savundum - ne kadar yanlış olduğumu çok az biliyordum.
Yıllar geçti ve React Native becerileri çok talep görmeye başladı. Yeni bir şey öğreneli uzun zaman olduğu için, neden denemeyeyim diye düşündüm. Bugün, büyük React Native savunucusuyum.
Eksileri:
- Artık Android Studio'yu kullanamazsınız
- React Native her uygulama veya özellik için kullanılamaz
- React Native yeni bir çerçevedir ve güncellemelerin mevcut kod tabanınız üzerinde olumsuz bir etkisi olabilir.
- JavaScript kesinlikle yazılan bir dil değil
- React Native'in çalışması için bir JavaScript motoru gerekir, bu da onu daha az performanslı hale getirebilir
Artıları:
- Öğrenmesi kolay
- Platform deneyimlerini eşleştirmek için yalnızca küçük ince ayarlar gerektiren, Android ve iOS uygulamaları arasında paylaşılan bir kod tabanı
- Canlı ve sıcak yeniden yükleme, yani artık sonsuz inşa süresi yok
- Her iki platform için yerel bileşenler
- Sürekli iyileştirme
- Aktif olarak büyüyen topluluk
- Çok sayıda kütüphane
- Expo, iOS için geliştirme yapmak için bir Mac'e sahip olma ihtiyacını ortadan kaldırıyor
- İş gücü kaynaklarında azalma—hala bazı Android/iOS yerel geliştirmeye ihtiyacınız olsa da, bu nadir olacaktır.
Daha da uzatabilirim ama burada duralım ve bu blog yazısının konusuna geçelim. Bu yazıda, dört adet React Native destekli Android uygulaması oluşturacağım:
- Sayacı artırmak ve azaltmak için düğmelere sahip temel bir sayaç
- r/pics alt dizininde arama yapmak için bir uygulama
- Genel bir giriş sayfası
- r/pics alt dizinine göz atmak için bir uygulama
IDE
Yukarıda bahsettiğim gibi, Android Studio'yu React Native geliştirme için kullanmamızın bir yolu yok. Bir yedek oyuncuya ihtiyacımız var. React Native, muhtemelen mevcut herhangi bir modern metin düzenleyicide (Atom, VS Code, Sublime Text, Brackets, vb.) geliştirilebilir, ancak Android Studio deneyimiyle geldiğimiz için favorim, aynı şirket tarafından oluşturulan WebStorm. WebStorm ücretli bir uygulama olmasına rağmen (yıllık 129$) Erken Erişim sürümünü kurabilirsiniz. WebStorm'un EAP yapısı ücretsizdir ve oldukça kararlıdır. Tamamen ücretsiz bir editör tercih ediyorsanız, VS Code'a gidin. Microsoft, bunun için harika React Native eklentisi bile geliştirdi ve çok iyi çalışıyor.
Yeni Proje Oluşturma
Önkoşullar: Bilgisayarınızda yüklü Android SDK, Node ve React Native.
Yeni React Native projesi oluşturmanın iki yolu vardır.
- Geleneksel yol. WebStorm GUI ile veya terminal komutuyla:
react-native init AwesomeToptalProject
- "React Native App Oluşturun" daha kolay yolu.
create-react-native-app AwesomeToptalProject
create-react-native-app
kullanıyorsanız, oluşturulan proje expo ile önyüklenir. Ayrıntılara girmeyeceğim, ancak temelde, bu, uygulamayı iOS'ta çalıştırmak için Xcode'un kurulu olmasına gerek olmadığı anlamına gelir. Ayrıca, expo.io'nun işlevselliği ve diğer bazı özellikleri aracılığıyla istemcinin her zaman güncel olmasını sağlamak daha kolaydır. Ancak yerel kod ekleyemezsiniz. Bu nedenle, belirli bir özellik geliştiriyorsanız, bir uygulamayı fuardan çıkarmanız ve bunun yerine normal bir React Native projesi kullanmanız gerekebilir.
İlk yöntemi kullanacağım.
Projeyi çalıştıralım. İlk önce bir emülatör açın veya cihazı bağlayın. Projeyi WebStorm GUI ile oluşturduysanız, tek yapmanız gereken bir konfigürasyon seçmektir. WebStorm'un sağ üst köşesinde, Çalıştır düğmesinin solundaki açılır menüyü tıklayın, Android'i seçin ve Çalıştır veya Hata Ayıkla'yı tıklayın. Projeyi Terminal ile oluşturduysanız, yeni bir React Native yapılandırması ekleyebilir veya Terminal kullanarak çalıştırabilirsiniz:
cd AwesomeToptalProject react-native run-android
Her şey yolunda giderse, aşağıdaki ekranla karşılaşacaksınız:

Yapı ve Temel Kurulum
Projedeki dikkate değer öğeler şunlardır:
- android - React Native desteği ile önceden yapılandırılmış Android Studio projesi.
- ios - React Native desteği ile önceden yapılandırılmış Xcode projesi.
- node_modules - React Native çerçevesini ve diğer Javascript kitaplıklarını içeren bir klasör.
- index.js - Uygulamamız için bir giriş noktası.
- App.js - İlk bileşen yüklendi.
Projenin kök dizininde bir “src” klasörü oluşturalım ve App.js'yi oraya taşıyalım. Yeni App.js konumuyla eşleşmesi için index.js içe aktarmalarını güncellemeniz gerekecek.
import App from './src/App';
App.js içindeki her şeyi silin ve şu kodu yapıştırın:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }
Yapıştırdığımız kod oldukça basit. render()
yöntemini geçersiz kılan ve Text
bileşenini döndüren bir App
sınıfı ( React.Component
alt öğesi) oluşturduk. React.Component
, JSX kullanarak UI oluşturmak için temel sınıftır. export default
değiştiricisi, sınıfı public
yapar.
Artık düzenimizi tasarlamaya başlamaya hazırız.
Flexbox ile Düzen
Flexbox
, LinearLayout
benzer, ancak Flexbox
, LinearLayout
yeteneklerinin çok ötesine geçer.
JSX'in bu pasajı:
<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>
Bu düzeni işler:
Bu XML iken:
<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>
Bunu oluşturur:
JSX kodu tanıdık geliyor, ha?! JSX ve Android XML'de benzer görünen mizanpajlar için bir "sözlük" (veya bir hile sayfası) oluşturalım.
Lütfen işlevlerin mutlaka eşit olmadığını unutmayın. React Native'deki düzen sistemi fikrini kavramak için React Native'e yeni başlayanlara yardım etmeye çalışıyorum. Ayrıntılı bilgi için lütfen resmi kılavuza bakın.
Bu JSX özelliğini düşünün:
flex: 1
Buna eşdeğerdir:
android:layout_width="match_parent" android:layout_height="match_parent"
JSX'in bu pasajı:
<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>
Ve bu 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>
Her ikisi de bu çıktıyı üretir:
Benzer şekilde, bu 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>
Ve bu 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>
Bunu oluştur:
Kap içinde doğru konumu elde etmek için en yaygın olarak flexDirection
, alignItems
ve justifyContent
özelliklerinin bir kombinasyonunu kullanacağız.
Bu 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>
Ve bu 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>
Bu düzeni üretecek:
Bu 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>
Ve bu 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>
Bu düzeni üretecek:
Bu 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>
Ve bu 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>
Bu düzeni üretecek:
Bu 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>
ve bu 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>
Bu düzeni üretecek:
flexDirection: row',
alignItems works on Y axis and
justifyContent works on X axis. Everything is mirrored for
flexDirection: column' works on X axis. Everything is mirrored for
- justifyContent
Y eksenini etkiler ve alignItems
Y eksenini etkiler.
justifyContent: 'esnek başlangıç' | yerçekimi="başlangıç|sol" |
alignItems: 'esnek başlangıç' | yerçekimi="başlangıç|sol" |
justifyContent: 'esnek uç' | yerçekimi="son|sağ" |
alignItems: 'esnek uç' | yerçekimi="son|sağ" |
Kendin dene. justifyContent
değerini space-around
, space-between
ve space-evenly
evenly olarak ayarlayın.
Durum Yönetimi
Uygulama durumunu güncellemek için React'in state
değişkenini kullanacaksınız. state
güncellendiğinde, render()
çağrılır.
Aşağıdaki kodu uygulamanıza kopyalayın:
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}); } }

AZALTMA ve ARTIRMA butonlarına tıklarsanız metnin sizin için otomatik olarak güncellendiğini göreceksiniz. textView.setText("Value " + number)
açıkça kullanmaya gerek yoktur.

Durum işlevselliği birçok nedenden dolayı kullanışlıdır:
- Değeri elde etme kolaylığı—belirli bir değişken için değeri nereden ve nasıl elde edeceğinizi her zaman bilirsiniz.
- Veriler belirli widget'lara bağlı değildir.
- Ortak değer değişikliğine bağlı birden fazla widget'a sahip olmak.
/r/pics için bir Arama Uygulaması Oluşturma
Artık temelleri kavradığımıza göre, biraz daha karmaşık bir şey oluşturalım: /r/pics için bir arama uygulaması. Reddit, basit bir JSON API uç noktası sağlar, bu nedenle doğru çalışması için kimlik doğrulaması almak üzere yan görevlere gitmemiz gerekmeyecektir.
React Native, yerleşik bir Fetch API sağlar. Çoğumuz muhtemelen Retrofit'e ve kullanım kolaylığına alıştığımız için, axios kullanacağız . Axios'u bir terminal komutuyla yükleyebilirsiniz.
yarn
kullanarak (Tercih ettiğim yöntem):
yarn add axios
veya npm
kullanarak:
npm install axios
İthalat:
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
Sınıfı oluşturun:
export default class App extends React.Component { }
Durumu başlatmak için. İhtiyacımız olacak:
- yükleniyor - Bir ilerleme çubuğu göstermek için.
- error - REST API isteği yapılırken bir hatanın oluşup oluşmadığını göstermek için.
- imgUrl - Aranan resmin önizlemesini yapmak için.
- metin - arama sorgusu.
state = {text: '', loading: false, error: null, imgUrl: null};
JSX kodunu ekleyin. TextInput
ve Image
bileşenleriyle dikey bir yerleşimimiz var.
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> ); }
Yeni şeyler:
onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }
İlk yöntem, TextWatcher
bileşeniyle EditText
benzer bir çalışma yapar. Dürüst olalım, React Native'de çok daha güzel.
İkinci yöntem, searchPicture()
tetikledikten sonra klavyede ( et.OnEditorActionListener
) dönüş tuşuna basıldığında çağrılır.
'&&' operatörü, birincisi zaten yanlışsa ikinci bir bağımsız değişkeni kontrol etmediğinden, imgUrl
boş veya tanımsız olmadığında Görüntü oluşturulur.
this.state.imgUrl
neden yanlış olduğunu merak ediyor olabilirsiniz. JavaScript'te mantıksal operatörler kullanırken, '' (boş bir dize), 0
, false
, null
veya undefined
dışında her şey doğrudur. Özel bir kontrole gerek yoktur.
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}) }) }
İşte başlıyoruz. Uygulama şimdi beklendiği gibi çalışmalıdır. Bir arama dizisi girin ve geri dönüş tuşuna basın.

Uygulamamız da ActivityIndicator
ve hataları oluşturmaya hazır olduğundan, Image
bileşeninden sonra biraz daha kod eklememiz gerekiyor:
{ //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> }
Render bileşenlerini ana render()
yönteminin dışına da taşıyabilirsiniz:
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> ); } }
Geriye sadece stiller kaldı. Bunları App
sınıfının dışına koyun.
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 } });
Artık, uygulama başlatıldığında yumuşak klavyeyi otomatik olarak açmak gibi biraz daha ince ayar ekleyebiliriz.
Lütfen TextInput
otomatik olarak odaklamanın daha kolay bir yolu olduğunu unutmayın ( autoFocus={true} prop
), ancak bu örnek için onu kullanmayacağız.
Prop ile TextInput
referans ekleyin:
ref={ref => this.searchInput = ref}
Ve componentDidMount()
yaşam döngüsü yöntemini şu şekilde geçersiz kılın:
componentDidMount(){ this.searchInput.focus(); }
Uygulamayı yeniden yükleyin ve klavye bizim için otomatik olarak açılır.
Bileşen Yaşam Döngüsü Yöntemleri
Zaten bir bileşen oluşturduk, ancak bir bileşenin ömrünü gözden geçirelim.
İşte React'in yaşam döngüsü akışı:
-
constructor()
- Uygulama başlatıldığında yapıcı her zaman çağrılır -
static _getDerivedStateFromProps_(props, state)
- Oluşturmadan önce ve güncellemeden sonra çağrılır. Durumu güncellemek için nesneyi döndürür. Hiçbir şeyi güncellemek için null döndürün. -
render()
- Her React Component sınıfı için render gereklidir. Görünümü oluşturmak için kullanılır. -
componentDidMount()
- Bileşen işlendikten ve görünüm ağacına monte edildikten sonra çağrılır. -
shouldComponentUpdate(nextProps, nextState)
- Durum veya donanım değişikliğinden sonra çağrılır. Her durum güncellemesinden sonra dönüş varsayılan olarak true olur. true döndürürserender()
ı çağırır. -
getSnapshotBeforeUpdate(prevProps, prevState)
- İşlenen çıktı işlenmeden hemen önce çağrılır. -
componentDidUpdate(prevProps, prevState, snapshot)
- Yeni güncelleme oluşturulduktan sonra çağrılır. İlkrender()
işleminden sonra çağrılmaz. -
componentWillUnmount()
- Bileşen sökülmeden ve yok edilmeden hemen önce çağrılır.
Yeniden Kullanılabilir Bileşenler
Proje üzerinde çalışırken genellikle yeniden kullanılabilir bileşenler oluşturmamız gerekir. Bir bileşen oluşturmanın iki yolu vardır:
-
React.Component
genişleten bir sınıf oluşturma. Yaşam döngüsü yöntemlerine ihtiyacımız varsa bu yöntem kullanılmalıdır. - Daha basit bir sözdizimi için Görünüm döndüren bir işlev yazarak.
Bileşen sınıflarını zaten oluşturduğumuz için bu örnek için bir fonksiyon oluşturalım.
<CardView>
için bir analoga ihtiyacımız olduğunu varsayalım. ./src
dizini altında bir “ortak” klasör oluşturun.
CardView.js
oluşturun.
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' } };
Yeni LoginForm
kullanarak 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' } }) } });
LoginForm
sınıfını App
sınıfına alın ve View
ile sarın
<View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>
Stillerdeki parametreleri değiştirirseniz, çok daha güzel görünen bir şey elde edebilirsiniz.
Navigasyon
Farklı sahnelerde gezinme, uygulamaların çoğu için önemli bir kısımdır. Bir Reddit /r/pics tarayıcı uygulaması oluşturacağız.
React Native'de navigasyon oluşturmak oldukça kolaydır.
Önkoşullar
-
yarn
veyanpm
ilereact-navigation
kurun -
yarn
veyaaxios
ilenpm
İki farklı bileşen oluşturarak başlayalım.
Not: Aşağıdaki kodun çoğu size zaten aşina olmalıdır. Bütün sınıfı yapıştıracağım.
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}}/>) } }
navigationOptions
Seçenekleri, React-Navigation tarafından otomatik olarak çağrılır.
Şimdi App.js'ye geçelim
Not: React-Navigation'da birçok navigasyon türü vardır. Bugün, StackNavigation
odaklanacağız. Ayrıntılı bilgi için lütfen resmi web sitesine bakın.
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' } );
Gördüğünüz gibi, tek yapmamız gereken bir navigasyon yönlendiricisi oluşturmak ve uygulamanın onu render etmesini sağlamak. Her şey yolunda giderse, işlevsel bir Reddit /r/pics tarayıcı uygulamamız olacak.
Android:
iOS:
React Native Harika!
Programlamaya başladığımdan beri tamamen mobil geliştirme deneyimlerim oldu. Ancak artık React: mobil, masaüstü ve web ile hemen hemen her şeyi kodlayabiliyorum.
Bir sonraki harika uygulamanızı React Native kullanarak geliştirmeye karar verirseniz, burada ve orada bazı tuhaflıkları ve bazı hataları olduğunu göreceksiniz, ancak React Native çok işlevsel ve çoğu proje için idealdir.