An asynchronous, unencrypted, persistent, key-value storage system for React Native. Head over to documentation to learn more. Pull requests are welcome. Please open an issue first to discuss what you would like to change. See the CONTRIBUTING file for more information. MIT.React Native Async Storage
Supported platforms
Getting Started
Contribution
License
Pada tutorial ini, kita akan membuat aplikasi pembaca berita dengan React Native. Dalam seri bagian kedua ini, saya akan berasumsi bahwa ini bukan aplikasi React Native pertamamu dan saya tidak akan menjelaskan secara detail tentang menyiapkan mesinmu dan menjalankan aplikasi di perangkat. Yang dikatakan, saya menjelaskan proses pengembangan yang sebenarnya secara rinci.
Table of Contents
- 1. Pengaturan Proyek
- Langkah 1: Membuat Aplikasi Baru
- Langkah 2: Menginstal Dependensi
- 2. Komponen Utama
- Komponen NewsItem
- Langkah 1: Mengimpor Komponen & Library
- Langkah 2: Membuat komponen NewsItems
- Langkah 3: Mengimplementasikan Fungsi render
- Langkah 4: Mengimplementasikan Fungsi componentDidMount
- Langkah 5: Mengimplementasikan Fungsi renderNews
- Langkah 6: Mengimplementasikan Fungsi updateNewsItemsUI
- Langkah 7: Memperbarui Local Storage
- Langkah 8: Mengambil Item Berita
- Langkah 9: Styling
Meskipun kita akan menerapkannya ke Android, kode yang digunakan dalam tutorial ini seharusnya juga bekerja pada iOS. Inilah hasil akhir tampilannya.
Kamu dapat menemukan kode sumber yang digunakan pada tutorial ini di GitHub.
Prasyarat
Jika kamu baru mengenal React Native dan belum menyiapkan mesinmu, pastikan untuk memeriksa panduan memulai dari dokumentasi React Native atau membaca tutorial pengantar Ashraff di Envato Tuts+. Jangan lupa untuk menginstal SDK Android jika kamu ingin mendeploynya ke Android atau menginstal Xcode dan SDK untuk iOS.
Setelah selesai, instal NodeJS dan tool command line React Native menggunakan npm.
npm install -g react-native-cli
1. Pengaturan Proyek
Kita sekarang siap untuk membuat proyek ini. Sebelum memulai, saya ingin memberikan gambaran singkat tentang bagaimana proyek digabungkan. Kita membuat dua komponen khusus:
-
NewsItems
yang merender item berita -
WebPage
yang merender halaman web saat pengguna mengetuk item berita
Ini kemudian diimpor ke file titik masuk utama untuk Android [index.android.js] dan untuk iOS [index.ios.js]. Itu saja yang perlu kamu ketahui sekarang.
Langkah 1: Membuat Aplikasi Baru
Mulailah dengan menavigasi ke direktori kerjamu. Buka jendela terminal baru di dalam direktori itu dan jalankan perintah berikut:
react-native init HnReader
Ini membuat folder baru bernama HnReader dan berisi file yang dibutuhkan untuk membuat aplikasi.
React Native sudah hadir dengan beberapa komponen bawaan, namun ada juga yang khusus yang dibangun oleh pengembang lain. Anda bisa menemukannya di website react.parts. Tidak semua komponen bekerja di Android dan iOS sekalipun. Bahkan beberapa komponen bawaannya tidak lintas-platform. Itulah mengapa kamu harus berhati-hati saat memilih komponen karena mereka mungkin berbeda pada setiap platform atau mungkin tidak bekerja dengan benar di setiap platform.
Sebaiknya masuk ke laman masalah repositoru GitHub dari komponen yang kamu rencanakan untuk digunakan dan telusuri salah satu dukungan android atau dukungan ios untuk segera memeriksa apakah komponen bekerja di kedua platform.
Langkah 2: Menginstal Dependensi
Aplikasi yang akan kita bangun bergantung pada beberapa library pihak ketiga dan komponen React. Kamu bisa menginstalnya dengan membuka package.json di direktori root kerjamu. Tambahkan yang berikut ini ke package.json:
{ "name": "HnReader", "version": "0.0.1", "private": true, "scripts": { "start": "react-native start" }, "dependencies": { "lodash": "^4.0.1", "moment": "^2.11.1", "react-native": "^0.18.1", "react-native-button": "^1.3.1", "react-native-gifted-spinner": "0.0.3" } }
Selanjutnya, buka jendela terminal di direktori kerja dan jalankan npm install
untuk menginstal dependensi yang ditentukan di package.json. Berikut adalah uraian singkat tentang apa yang masing-masing library lakukan pada proyek ini:
- lodash digunakan untuk menyingkat string. Ini mungkin sedikit berlebihan, tapi satu baris kode yang harus kamu tulis berarti satu kewajiban yang lebih kecil.
- moment digunakan untuk menentukan apakah item berita di local storagel sudah ada di sana untuk satu hari.
- react-native adalah framework React Native. Ini terinstall secara default saat anda menjalankan
react-native init
tadi. - react-native-button adalah komponen react native yang digunakan untuk membuat tombol.
- react-native-gifted-spinner digunakan sebagai indikator aktivitas saat membuat request jaringan.
2. Komponen Utama
Seperti yang saya sebutkan sebelumnya, titik masuk untuk semua proyek React Native adalah index.android.js dan index.ios.js. Itulah fokus pada bagian ini. Ganti isi file-file itu dengan yang berikut ini:
'use strict'; var React = require['react-native']; var { AppRegistry, StyleSheet, Navigator } = React; var NewsItems = require['./components/news-items']; var WebPage = require['./components/webpage']; var ROUTES = { news_items: NewsItems, web_page: WebPage }; var HnReader = React.createClass[{ renderScene: function[route, navigator] { var Component = ROUTES[route.name]; return [ ]; }, render: function[] { return [ { return Navigator.SceneConfigs.FloatFromRight; }} /> ]; }, }]; var styles = StyleSheet.create[{ container: { flex: 1 } }]; AppRegistry.registerComponent['HnReader', [] => HnReader];
Biarkan saya memecahnya.
Pertama, kita aktifkan mode strict [ketat] dengan menggunakan direktif use script
. Hal ini membuat parser melakukan lebih banyak pemeriksaan pada kodemu. Sebagai contoh, ini akan mengeluh jika kamu menginisialisasi variabel tanpa menambahkan kata kunci var
.
'use strict';
Selanjutnya, kita mengimpor framework React Native. Ini memungkinkan kita membuat komponen khusus dan menambahkan styling ke aplikasi.
var React = require['react-native'];
Kita kemudian mengekstrak semua fungsi yang kita butuhkan dari
objek React
.
var { AppRegistry, StyleSheet, Navigator } = React;
Jika kamu baru mengenal ES6 [ECMAScript 6], snippet di atas identik dengan:
var AppRegistry = React.AppRegistry; var StyleSheet = React.StyleSheet; var Navigator = React.Navigator;
Ini adalah sintaktis manis yang diperkenalkan di ES6 untuk membuat penugasan sifat objek ke variabel lebih mudah. Ini disebut destructuring assignment [penugasan destrukturisasi].
Berikut adalah uraian singkat tentang masing-masing properti yang telah kita ekstrak:
-
AppRegistry
digunakan untuk mendaftarkan komponen utama aplikasi. -
StyleSheet
digunakan untuk mendeklarasikan style yang akan digunakan oleh komponen. -
Navigator
digunakan untuk beralih antar halaman aplikasi yang berbeda
Selanjutnya, kita mengimpor komponen khusus yang digunakan oleh aplikasi. Kita akan membuatnya nanti.
var NewsItems = require['./components/news-items']; var WebPage = require['./components/webpage'];
Buat variabel ROUTES
dan tetapkan sebuah objek menggunakan dua komponen di atas sebagai nilai untuk propertinya. Ini memungkinkan kita menampilkan komponen dengan mengacu pada masing-masing tombol yang telah kita
definisikan.
var ROUTES = { news_items: NewsItems, web_page: WebPage };
Buat komponen utama aplikasi dengan memanggil metode createClass
dari objek React
. Metode createClass
menerima sebuah objek sebagai argumennya.
var HnReader = React.createClass[{ ... }];
Di dalam objek adalah metode renderScene
, yang dipanggil kapan pun route berubah. route
dan navigator
diteruskan sebagai argumen untuk metode ini. route
berisi informasi tentang route saat ini [misalnya, nama route].
navigator
berisi metode yang dapat digunakan untuk menavigasi di antara route yang
berbeda. Di dalam metode renderScene
, kita mendapatkan komponen yang ingin kita buat dengan meneruskan nama route saat ini ke objek ROUTES
. Selanjutnya, kita membuat komponen dan melewati route
, navigator
, dan url
sebagai atribut. Nantinya, kamu akan melihat bagaimana ini digunakan di dalam masing-masing komponen. Untuk saat ini, ingatlah bahwa ketika kamu ingin meneruskan data dari komponen utama ke komponen turunan, yang harus kamu lakukan adalah menambahkan atribut baru dan menggunakan
data yang ingin kamu lewati sebagai nilainya.
renderScene: function[route, navigator] { var Component = ROUTES[route.name]; //get the component for this specific route //render the component and pass along the route, navigator and the url return [ ]; },
Metode render
adalah metode yang diperlukan saat membuat komponen karena bertanggung jawab untuk membuat antarmuka pengguna dari komponennya. Dalam metode ini, kita membuat komponen Navigator
dan meneruskan beberapa atribut.
render: function[] { return [ { return Navigator.SceneConfigs.FloatFromRight; }} /> ]; },
Izinkan saya menjelaskan apa yang masing-masing atribut lakukan:
-
style
digunakan untuk menambahkan style ke komponen. -
initialRoute
digunakan untuk menentukan route awal yang akan digunakan oleh navigator. Seperti yang kamu lihat, kami telah meneruskan sebuah objek yang berisi propertinama
dengan nilainya yang diatur kenews_items
. Objek ini adalah apa yang diteruskan ke argumenroute
dari metoderenderScene
, yang telah kita definisikan sebelumnya. Ini berarti kode khusus ini akan menjadikan komponenNewsItems
secara default.
var Component = ROUTES[route.name];
url
diatur ke string kosong karena kita tidak memiliki halaman web untuk ditampilkan secara default.
-
renderScene
bertanggung jawab untuk merender komponen untuk route tertentu. -
configureScene
bertanggung jawab untuk menentukan animasi dan isyarat yang akan digunakan saat menavigasi antar route. Dalam kasus ini, kita meneruskan sebuah fungsi yang mengembalikan animasiFloatFromRight
. Ini berarti bahwa, saat menavigasi ke route dengan indeks yang lebih tinggi, halaman baru melayang dari kanan ke kiri. Dan saat kembali, itu melayang kiri ke kanan. Ini juga menambahkan isyarat menggeser ke kiri sebagai sarana untuk kembali ke route sebelumnya.
[] => { return Navigator.SceneConfigs.FloatFromRight; }
Style didefinisikan setelah definisi komponen utama. Kita memanggil metode create
dari objek StyleSheet
dan meneruskannya dalam objek yang berisi gaya. Dalam kasus ini, kita hanya memiliki satu, yang menentukan bahwa ia akan menempati keseluruhan layar.
var styles = StyleSheet.create[{ container: { flex: 1 } }];
Terakhir, kita mendaftarkan komponennya.
AppRegistry.registerComponent['HnReader', [] => HnReader];
Komponen NewsItem
Komponen NewsItem
digunakan untuk merender
item berita. Komponen khusus disimpan dalam direktori components. Di dalam direktori ini, buat news-items.js dan tambahkan kode berikut ke dalamnya:
'use strict'; var React = require['react-native']; var { AppRegistry, StyleSheet, Text, ListView, View, ScrollView, TouchableHighlight, AsyncStorage } = React; var Button = require['react-native-button']; var GiftedSpinner = require['react-native-gifted-spinner']; var api = require['../src/api.js']; var moment = require['moment']; var TOTAL_NEWS_ITEMS = 10; var NewsItems = React.createClass[{ getInitialState: function[] { return { title: 'HN Reader', dataSource: new ListView.DataSource[{ rowHasChanged: [row1, row2] => row1 !== row2, }], news: {}, loaded: false } }, render: function[] { return [ {this.state.title} { !this.state.loaded && } { this.state.loaded && } ]; }, componentDidMount: function[] { AsyncStorage.getItem['news_items'].then[[news_items_str] => { var news_items = JSON.parse[news_items_str]; if[news_items != null]{ AsyncStorage.getItem['time'].then[[time_str] => { var time = JSON.parse[time_str]; var last_cache = time.last_cache; var current_datetime = moment[]; var diff_days = current_datetime.diff[last_cache, 'days']; if[diff_days > 0]{ this.getNews[]; }else{ this.updateNewsItemsUI[news_items]; } }]; }else{ this.getNews[]; } }].done[]; }, renderNews: function[news] { return [ {news.title} ]; }, viewPage: function[url]{ this.props.navigator.push[{name: 'web_page', url: url}]; }, updateNewsItemsUI: function[news_items]{ if[news_items.length == TOTAL_NEWS_ITEMS]{ var ds = this.state.dataSource.cloneWithRows[news_items]; this.setState[{ 'news': ds, 'loaded': true }]; } }, updateNewsItemDB: function[news_items]{ if[news_items.length == TOTAL_NEWS_ITEMS]{ AsyncStorage.setItem['news_items', JSON.stringify[news_items]]; } }, getNews: function[] { var TOP_STORIES_URL = '//hacker-news.firebaseio.com/v0/topstories.json'; var news_items = []; AsyncStorage.setItem['time', JSON.stringify[{'last_cache': moment[]}]]; api[TOP_STORIES_URL].then[ [top_stories] => { for[var x = 0; x { news_items.push[story]; this.updateNewsItemsUI[news_items]; this.updateNewsItemDB[news_items]; } ]; } } ]; } }]; var styles = StyleSheet.create[{ container: { flex: 1 }, header: { backgroundColor: '#FF6600', padding: 10, flex: 1, justifyContent: 'space-between', flexDirection: 'row' }, body: { flex: 9, backgroundColor: '#F6F6EF' }, header_item: { paddingLeft: 10, paddingRight: 10, justifyContent: 'center' }, header_text: { color: '#FFF', fontWeight: 'bold', fontSize: 15 }, button: { borderBottomWidth: 1, borderBottomColor: '#F0F0F0' }, news_item: { paddingLeft: 10, paddingRight: 10, paddingTop: 15, paddingBottom: 15, marginBottom: 5 }, news_item_text: { color: '#575757', fontSize: 18 } }]; module.exports = NewsItems;
Langkah 1: Mengimpor Komponen & Library
Pertama, kita mengimpor komponen dan library yang kita butuhkan untuk komponen NewsItem
. Kita juga membuat variabel global yang menyimpan jumlah item berita yang akan di-cache.
'use strict'; var React = require['react-native']; var { AppRegistry, StyleSheet, Text, ListView, View, ScrollView, TouchableHighlight, AsyncStorage } = React; var Button = require['react-native-button']; var GiftedSpinner = require['react-native-gifted-spinner']; var api = require['../src/api.js']; var moment = require['moment']; var TOTAL_NEWS_ITEMS = 10;
Kita
menggunakan beberapa komponen yang belum kita gunakan tadi.
-
Text
digunakan untuk menampilkan teks dalam React Native. -
View
adalah blok bangunan dasar untuk membuat komponen. Anggap saja itu sebagaidiv
di halaman web. -
ListView
digunakan untuk merender suatu array dari objek. -
ScrollView
digunakan untuk menambahkan scroll bar. React Native tidak seperti halaman web. Scroll bar tidak ditambahkan secara otomatis saat konten lebih besar dari tampilan atau layar. Itu sebabnya kita perlu menggunakan komponen ini. -
TouchableHighlight
digunakan untuk membuat komponen menanggapi event sentuhan. -
AsyncStorage
sebenarnya bukan komponen. Ini adalah API yang digunakan untuk menyimpan data lokal di React Native. -
Button
adalah komponen pihak ketiga untuk membuat tombol. -
GiftedSpinner
digunakan untuk membuat spinner saat memuat data dari jaringan. -
api
adalah modul khusus yang membungkusfetch
, cara React Native untuk membuat permintaan jaringan. Ada banyak kode boilerplate yang dibutuhkan untuk mendapatkan data yang dikembalikan oleh permintaan jaringan dan oleh karena itu kita membungkusnya di dalam modul. Ini memungkinkan kita menulis lebih sedikit kode saat membuat permintaan jaringan. -
moment
adalah library yang digunakan untuk segala hal yang berhubungan dengan waktu.
Langkah 2: Membuat komponen NewsItems
Selanjutnya, kita
membuat komponen NewsItems
:
var NewsItems = React.createClass[{ ... }];
Komponen ini adalah fungsi getInitialState
, yang digunakan untuk menentukan state default untuk komponen ini. Dalam React Native, state digunakan untuk menyimpan data yang tersedia di seluruh komponen. Di sini, kita menyimpan judul aplikasi, dataSource
untuk komponen ListView
, item news
saat ini dan nilai boolean, loaded
, yang memberitahu apakah item berita saat ini sedang dimuat dari jaringan atau tidak. Variabel loaded
digunakan untuk menentukan
apakah atau tidak untuk menampilkan spinner. Kita atur ke false
sehingga spinner dapat dilihat secara default.
Setelah item berita dimuat, baik dari local storage atau dari jaringan, itu diset ke true
untuk menyembunyikan spinner. dataSource
digunakan untuk mendefinisikan blueprint dari sumber data yang digunakan untuk komponen ListView
. Anggap saja sebagai class induk di mana setiap sumber data yang akan kamu definisikan akan mewarisinya. Hal ini memerlukan sebuah objek
yang mengandung fungsi rowHasChanged
, yang memberitahukan ListView
untuk kembali merender ulang ketika sebuah baris telah berubah.
Akhirnya, berita objek berisi nilai awal untuk sumber data ListView.
getInitialState: function[] { return { title: 'HN Reader', dataSource: new ListView.DataSource[{ rowHasChanged: [row1, row2] => row1 !== row2, }], news: {}, loaded: false } },
Langkah 3: Mengimplementasikan Fungsi render
Fungsi render
merender antarmuka pengguna untuk komponen ini. Pertama, kira bungkus semuanya dalam sebuah View
. Kemudian, di dalamnya kita memiliki header dan body. Header
berisi judul dan spinner. Body berisi ListView
. Segala sesuatu di dalam body dibungkus di dalam ScrollView
sehingga scroll bar akan secara otomatis ditambahkan jika konten melebihi ruang yang tersedia.
render: function[] { return [ {this.state.title} { !this.state.loaded && } { this.state.loaded && } ]; },
Di dalam header ada dua view:
- satu berisi judul
- satu berisi spinner
Kita melakukan itu dengan cara ini daripada mengeluarkan teks dan spinner secara langsung sehingga kita bisa mengendalikan styling dengan menggunakan flexbox,
Kamu dapat melihat bagaimana hal ini dilakukan di bagian styling, nanti.
Kita dapat merujuk kepada judul yang disimpan di state-nya dengan menggunakan this.state
, diikuti oleh nama properti. Seperti yang mungkin kamu perhatikan, setiap kali kita perlu merujuk pada sebuah objek, kita membungkusnya dengan kurung kurawal. Pada view yang lain, kita sedang memeriksa jika properti loaded
di state diatur ke false
dan, jika itu adalah, kita keluaran pemintal.
{this.state.title} { !this.state.loaded && }
Berikutnya adalah
body.
{ this.state.loaded && }
Perhatikan bahwa kita telah mengirimkan atribut ref
ke ScrollView
. ref
adalah atribut yang telah ditetapkan dalam React Native yang memungkinkan kita untuk menetapkan pengenal untuk sebuah komponen. Kami dapat menggunakan pengenal ini untuk merujuk ke komponennya dan memanggil metode-metodenya. Berikut adalah contoh bagaimana ini bekerja:
scrollToTop: function[]{ this.refs.scrollView.scrollTo[0]; }
Kamu kemudian dapat memiliki tombol dan memanggil fungsi itu saat ditekan. Ini secara otomatis akan men-scroll
ScrollView
ke puncak komponen.
scroll to top
Kita tidak akan menggunakan ini di aplikasi, tetapi ada baiknya untuk tahu bahwa itu ada.
Di dalam ScrollView
, kita memeriksa jika properti loaded
di state sudah diset ke true
. Jika itu true
, itu berarti bahwa sumber data sudah tersedia untuk digunakan oleh ListView
dan kita dapat merendernya.
{ this.state.loaded && }
Kami telah meneruskan atribut berikut di ListView
:
-
initialListSize
digunakan untuk menentukan berapa banyak baris untuk dirender ketika komponen awalnya dipasang. Kita telah mengesetnya ke1
, yang berarti itu akan mengambil satu frame untuk membuat merender setiap baris. Saya telah mengesetnya ke1
sebagai bentuk optimasi kinerja sehingga pengguna melihat sesuatu sesegera mungkin. -
dataSource
adalah sumber data yang untuk digunakan. -
renderRow
adalah fungsi yang digunakan untuk merender setiap baris dalam daftar.
Langkah 4: Mengimplementasikan Fungsi componentDidMount
Selanjutnya, kita memiliki fungsi componentDidMount
, yang akan dipanggil ketika komponen ini dipasang:
componentDidMount: function[] { AsyncStorage.getItem['news_items'].then[[news_items_str] => { var news_items = JSON.parse[news_items_str]; if[news_items != null]{ AsyncStorage.getItem['time'].then[[time_str] => { var time = JSON.parse[time_str]; var last_cache = time.last_cache; var current_datetime = moment[]; var diff_days = current_datetime.diff[last_cache, 'days']; if[diff_days > 0]{ this.getNews[]; }else{ this.updateNewsItemsUI[news_items]; } }]; }else{ this.getNews[]; } }].done[]; },
Dalam fungsi tersebut, kita mencoba untuk mengambil item berita yang saat ini disimpan dalam local storage. Kita menggunakan metode getItem
dari API AsyncStorage
. Itu mengembalikan sebuah promise sehingga kita bisa mendapatkan akses ke data yang dikembalikan dengan memanggil metode then
kemudian meneruskannya sebuah dalam
fungsi:
AsyncStorage.getItem['news_items'].then[[news_items_str] => { ... }].done[];
AsyncStorage
hanya dapat menyimpan string data sehingga kita menggunakan JSON.parse
untuk mengkonversi string JSON kembali ke objek JavaScript. Jika itu null
, kita memanggil metode getNews
, yang mengambil data dari jaringan.
var news_items = JSON.parse[news_items_str]; if[news_items != null]{ ... }else{ this.getNews[]; }
Jika tidak kosong, kita menggunakan AsyncStorage
untuk mengambil waktu terakhir dari item berita yang disimpan dalam local storage. Kita kemudian membandingkannya dengan waktu saat ini. Jika perbedaan ini setidaknya sehari [24 jam], kita
mengambil item berita dari jaringan. Jika tidak, kita menggunakan yang ada di penyimpanan lokal.
AsyncStorage.getItem['time'].then[[time_str] => { var time = JSON.parse[time_str]; var last_cache = time.last_cache; //extract the last cache time var current_datetime = moment[]; //get the current time //get the difference in days var diff_days = current_datetime.diff[last_cache, 'days']; if[diff_days > 0]{ this.getNews[]; //fetch from the network }else{ this.updateNewsItemsUI[news_items]; //use the one in the cache } }];
Langkah 5: Mengimplementasikan Fungsi renderNews
Berikutnya adalah fungsi untuk merender setiap baris dalam daftar. Sebelumnya di ListView
, kita telah mendefinisikan atribut renderRow
, yang memiliki nilai this.renderNews
. Ini adalah fungsi itu.
Item saat ini dalam perulangan dilteruskan sebagai sebuah argumen untuk
fungsi ini. Hal ini memungkinkan kita untuk mengakses title
dan url
dari setiap item berita. Semuanya terbungkus di dalam komponen TouchableHighlight
dan di dalamnya kita tampilkan judul setiap item berita.
Komponen TouchableHighlight
menerima atribut onPress
, yang menetapkan fungsi yang mengeksekusi ketika pengguna mengetuk item-nya. Di sini kita panggil fungsi viewPage
dan mengikat URL untuk itu. underlayColor
menentukan warna background dari komponen ketika diketuk.
renderNews: function[news] { return [ {news.title} ]; },
Pada fungsi
viewPage
, kami mendapatkan atribut navigator yang telah kita teruskan sebelumnya dari index.android.js
via props. Di React Native, props digunakan untuk mengakses atribut yang diteruskan dari komponen induk. Kita menyebutnya sebagai this.props
, diikuti oleh nama atribut.
Di sini, kita menggunakan this.props.navigator
untuk merujuk ke objek navigator
. Kita kemudian memanggil metode push
untuk mendorong route web_page
ke navigator dengan URL halaman web yang akan dibuka oleh komponen
WebPage
. Hal ini membuat transisi aplikasi ke komponen WebPage
.
viewPage: function[url]{ this.props.navigator.push[{name: 'web_page', url: url}]; },
Langkah 6: Mengimplementasikan Fungsi updateNewsItemsUI
Fungsi updateNewsItemsUI
memperbarui sumber data dan state berdasarkan array item berita yang diteruskan sebagai sebuah argumen. Kita hanya melakukannya jika total news_items
sama dengan nilai yang kita tetapkan sebelumnya untuk TOTAL_NEWS_ITEMS
. Di React Native, memperbarui state memicu antarmuka
pengguna untuk merender ulang. Ini berarti bahwa panggilan setState
dengan sumber data baru me-refresh antarmuka pengguna dengan item baru.
updateNewsItemsUI: function[news_items]{ if[news_items.length == TOTAL_NEWS_ITEMS]{ var ds = this.state.dataSource.cloneWithRows[news_items]; //update the data source //update the state this.setState[{ 'news': ds, 'loaded': true }]; } },
Langkah 7: Memperbarui Local Storage
Fungsi updateNewsItemDB
memperbarui berita yang disimpan dalam local storage. Kita menggunakan fungsi JSON.stringify
untuk mengkonversi array ke dalam sebuah string JSON sehingga kita dapat menyimpannya menggunakan AsyncStorage
.
updateNewsItemDB: function[news_items]{ if[news_items.length == TOTAL_NEWS_ITEMS]{ AsyncStorage.setItem['news_items', JSON.stringify[news_items]]; } },
Langkah 8: Mengambil Item Berita
Fungsi getNews
memperbarui item local storage yang terakhir kali menyimpan data yang di-cache, mengambil item berita dari API Hacker News, memperbarui antarmuka pengguna dan local storage berdasarkan item baru yang diambil.
getNews: function[] { var TOP_STORIES_URL = '//hacker-news.firebaseio.com/v0/topstories.json'; var news_items = []; AsyncStorage.setItem['time', JSON.stringify[{'last_cache': moment[]}]]; api[TOP_STORIES_URL].then[ [top_stories] => { for[var x = 0; x { news_items.push[story]; this.updateNewsItemsUI[news_items]; this.updateNewsItemDB[news_items]; } ]; } } ]; }
Sumber cerita teratas di API Hacker News mengembalikan array yang terlihat seperti ini:
[ 10977819, 10977786, 10977295, 10978322, 10976737, 10978069, 10974929, 10975813, 10974552, 10978077, 10978306, 10973956, 10975838, 10974870...
Ini adalah pengidentifikasi item teratas yang diposting di Hacker News. Itulah mengapa kita perlu melakukan perulangan melalui array ini dan membuat request jaringan untuk setiap item untuk mendapatkan rincian sebenarnya, seperti judul dan URL.
Kita kemudian mendorongnya ke array news_items
dan memanggil fungsi updateNewsItemsUI
dan updateNewsItemDB
untuk memperbarui antarmuka pengguna dan local storage.
for[var x = 0; x { news_items.push[story]; this.updateNewsItemsUI[news_items]; this.updateNewsItemDB[news_items]; } ]; }
Langkah 9: Styling
Tambahkan style berikut ini:
var styles = StyleSheet.create[{ container: { flex: 1 }, header: { backgroundColor: '#FF6600', padding: 10, flex: 1, justifyContent: 'space-between', flexDirection: 'row' }, body: { flex: 9, backgroundColor: '#F6F6EF' }, header_item: { paddingLeft: 10, paddingRight: 10, justifyContent: 'center' }, header_text: { color: '#FFF', fontWeight: 'bold', fontSize: 15 }, button: { borderBottomWidth: 1, borderBottomColor: '#F0F0F0' }, news_item: { paddingLeft: 10, paddingRight: 10, paddingTop: 15, paddingBottom: 15, marginBottom: 5 }, news_item_text: { color: '#575757', fontSize: 18 } }];
Sebagian besar itu adalah CSS standar, namun perhatikan bahwa
kita telah mengganti tanda hubung dengan sintaks kurung kurawal. Ini bukan karena kita mendapatkan kesalahan sintaks jika kita menggunakan sesuatu seperti padding-left
. Hal ini karena diharuskan oleh React Native. Juga perhatikan bahwa tidak semua properti css dapat digunakan.
Yang dikatakan, berikut ini adalah beberapa deklarasi yang mungkin tidak terlalu intuitif, terutama jika kamu belum pernah menggunakan flexbox sebelumnya:
container: { flex: 1 }, header: { backgroundColor: '#FF6600', padding: 10, flex: 1, justifyContent: 'space-between', flexDirection: 'row' }, body: { flex: 9, backgroundColor: '#F6F6EF' },
Berikut ini adalah versi
sederhana dari markup untuk komponen NewsItems
untuk membantumu memvisualisasikan itu:
... ...
Kami telah menetapkan container
ke flex: 1
, yang berarti menempati seluruh layar. Di dalam container
kita memiliki header
dan body
, yang telah kita set ke flex: 1
dan flex: 9
, masing-masingnya. Dalam kasus ini, flex: 1
tidak akan menempati seluruh layar karena header
memiliki saudara kandung. Keduanya akan berbagi keseluruhan layar. Ini berarti bahwa seluruh layar akan dibagi
menjadi sepuluh bagian karena kita memiliki flex: 1
dan flex: 9
. Nilai untuk flex
untuk masing-masing saudara kandung ditambahkan.
header
menempati 10% dari layar dan body menempati 90% dari itu. Ide dasarnya adalah memilih nomor yang akan mewakili tinggi atau lebar seluruh layar dan kemudian masing-masing saudara kandung mengambil sepotong dari nomor ini Jangan berlebihan dengan ini, meskipun. Kamu tidak ingin menggunakan 1000 kecuali kamu ingin men-deploy aplikasi mu
di bioskop. Saya menemukan sepuluh menjadi nomor ajaib saat bekerja dengan tinggi badan.
Untuk header
, kita telah menetapkan gaya berikut:
header: { backgroundColor: '#FF6600', padding: 10, flex: 1, justifyContent: 'space-between', flexDirection: 'row' },
Dan untuk me-refresh ingatanmu, berikut adalah markup sederhana dari apa yang ada di dalam header:
... ...
Dan dengan style yang ditambahkan kepadanya:
header_item: { paddingLeft: 10, paddingRight: 10, justifyContent: 'center' },
Kita telah menetapkan flexDirection
ke row
dan justifyContent
ke space-between
pada induknya, yaitu header
. Ini berarti turunannya akan merata, dengan turunan pertama
di awal baris dan turunan terakhir di akhir baris.
Secara default flexDirection
diatur ke column
, yang berarti bahwa setiap turunan menempati seluruh baris karena gerakan horisontal. Menggunakan row
akan membuat aliran vertikal sehingga setiap turunan akan berdampingan. Jika kamu masih bingung tentang Flexbox atau kamu ingin mempelajari lebih lanjut tentang hal itu, kemudian periksa CSS: Flexbox Essentials.
Terakhir, menampakkan komponen untuk dunia luar:
module.exports = NewsItems;
Kesimpulan
Pada titik ini, kamu seharusnya memiliki ide bagus tentang bagaimana melakukan banyak hal dengan cara React Native. Secara khusus, kamu telah belajar bagaimana untuk membuat sebuah proyek React Native baru, menginstal library pihak ketiga melalui npm, menggunakan berbagai komponen dan menambahkan styling ke aplikasi.
Pada artikel selanjutnya, kita akan melanjutkan dengan menambahkan komponen WebPage
untuk aplikasi pembaca berita. Jangan ragu untuk meninggalkan
pertanyaan atau komentar pada bagian komentar di bawah ini.