React Native ではてなブックマークアプリをつくってみる 2
スワイプダウンして更新するやつを追加してみた
RefreshControl を使って、画面をスワイプダウンして ホッテントリ一覧を更新できるようにしてみた。
// components/BookmarkList.js import React from 'react' import { Text, View, FlatList, RefreshControl } from 'react-native' import BookmarkListItem from './BookmarkListItem' export default class BookmarkList extends React.Component { state = { refreshing: true, items: [] } componentDidMount () { this._fetchFeed() } _fetchFeed = async () => { const feed = await this.props.fetchEntry() const items = feed.item console.dir(items) this.setState({ refreshing: false, items }) } _onRefresh = () => { this.setState({ refreshing: true }) this._fetchFeed() } _keyExtractor = (item, index) => item.link _renderItem = ({ item }) => ( <BookmarkListItem item={item} /> ) render () { return ( <FlatList data={this.state.items} extraData={this.state.items} keyExtractor={this._keyExtractor} renderItem={this._renderItem} refreshControl={ <RefreshControl refreshing={this.state.refreshing} onRefresh={this._onRefresh.bind(this)} /> } /> ) } }
こんな感じになりました。
リポジトリはこちら。
React Native ではてなブックマークアプリをつくってみる 1
最近、React Native のお勉強をしているので試しにはてなブックマークアプリをつくってみたい。
要件定義
僕ははてブを見る時にまずブコメからみる習慣があるので、下記のようなアプリにしたい。
- ホッテントリの一覧がでる
- 一覧のアイテムをタップするとまずブックマークコメントが表示される
- メタブックマークがあればメタブ一覧を表示するボタンが出る
- ブックマークされたページはブコメ一案にあるボタンを押すと閲覧できる
- その際、魚拓があれば魚拓を閲覧することもできるようにしたい
そんな感じで作っていきます
まずはプロジェクトを初期化
Getting Started · React Native に載ってるとおりにプロジェクトを作成する。
アプリ名はとりあえず「HBCommentFirst」と名づけた。
$ yarn global add create-react-native-app $ create-react-native-app HBCommentFirst $ cd HBCommentFirst $ yarn start
コンソールにQRコードが表示されるので、スマホにインストールした Expoクライアントアプリ からQRを読み込むだけでアプリを実機で確認しながら開発できる。しかも、ブラウザでデバッグもできる。超便利。
ホットエントリーを読み込む
とりあえず、はてなブックマークのホッテントリを読み込んでJSONにする関数を書いてみる。
ちなみに、Networking · React Native を参考にした。
// libs/HatenaBookmark.js import X2JS from 'x2js' const hotentry = 'http://b.hatena.ne.jp/hotentry.rss' /** * ホットエントリーを読み込んでJSONを返す */ export const fetchHotEntry = () => { return fetchRss(hotentry) } /** * RSSをfetchしてJSONを返す */ const fetchRss = async (url) => { const response = await fetch(url) const rssText = await response.text() const x2js = new X2JS() const rss = x2js.xml2js(rssText) return rss.RDF }
// App.js import React from 'react' import { StyleSheet, Text, View } from 'react-native' import { fetchHotEntry } from './libs/HatenaBookmark' export default class App extends React.Component { // ホットエントリーを読み込んで結果を出力 async componentDidMount() { const feed = await fetchHotEntry() console.dir(feed) } render() { return ( <View style={styles.container}> <Text>Hello!</Text> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } })
デバッガーにはこんな感じで出力される。
リストとして表示してみる
FlatList コンポーネントを利用して、読み込んだホッテントリのフィードをリストとして表示してみる。
// components/BookmarkListItem.js import React from 'react' import { StyleSheet, Text, View } from 'react-native' export default class BookmarkListItem extends React.Component { render () { const item = this.props.item return ( <View style={styles.item}> <Text style={styles.itemTitle} numberOfLines={3} ellipsizeMode={'tail'} > { item.title } </Text> <Text style={styles.itemDesc} numberOfLines={2} ellipsizeMode={'tail'} > { item.description } </Text> <Text style={styles.itemCount}>{ item.bookmarkcount.toString() } users</Text> </View> ) } } const styles = StyleSheet.create({ item: { padding: 15, borderBottomColor: '#eee', borderBottomWidth: 1 }, itemTitle: { fontSize: 14, lineHeight: 14 * 1.6, fontWeight: 'bold' }, itemDesc: { marginTop: 8, fontSize: 13, lineHeight: 13 * 1.6, color: '#666' }, itemCount: { marginTop: 8, fontSize: 13, color: '#c00' } })
// components/BookmarkList.js import React from 'react' import { Text, View, FlatList } from 'react-native' import BookmarkListItem from './BookmarkListItem' export default class BookmarkList extends React.Component { state = { items: [] } async componentDidMount () { const feed = await this.props.fetchEntry() const items = feed.item console.dir(items) this.setState({ items }) } _keyExtractor = (item, index) => item.link _renderItem = ({ item }) => ( <BookmarkListItem item={item} /> ) render () { return ( <FlatList data={this.state.items} extraData={this.state.items} keyExtractor={this._keyExtractor} renderItem={this._renderItem} /> ) } }
// App.js import React from 'react' import BookmarkList from './components/BookmarkList' import { View } from 'react-native' import { fetchHotEntry } from './libs/HatenaBookmark' export default class App extends React.Component { render() { return ( <View style={{marginTop: 20}}> <BookmarkList fetchEntry={fetchHotEntry} /> </View> ) } }
こんな感じになりました。
Text モジュールのnumberOfLines
とellipsizeMode
プロパティが非常に便利で感動した。
とりあえず今日は以上。
ちなみにソースコード一式は下記にあります。