はじめに
新卒エンジニア2ヶ月目。
Webやネイティブに関する知識は全く無かったのでいろんなものを参考に自分でも作ってみる。
Qiitaのクライアントアプリ作れたら面白そうだなと思ったので調べたら似たような(というかほぼやりたいこと)記事https://qiita.com/y_matsuwitter/items/a7fc88e566b80b4c1eeaがあった。ES5以前に書かれているようだったので自分なりにES6バージョンにしてみた。
コードについて
GitHubにも上げてあるhttps://github.com/Ikeponias/qiita-client。
RootNavigator.js
import React, { Component } from 'react';
import {
NavigatorIOS,
StyleSheet,
} from 'react-native';
import QiitaItemsListContainer from '../containers/QiitaItemsListContainer';
export default class RootNavigator extends Component {
render() {
return (
<NavigatorIOS
style={ styles.navigator }
initialRoute={{
component: QiitaItemsListContainer,
title: 'ReactQiita',
}}
/>
);
}
}
// 各種デザイン要素
var styles = StyleSheet.create({
navigator: {
flex: 1
},
});
React Native Navigationを使っていたが、たまにはNavigatorIOSを使ってみた(参考にしたサイトにもあったので)。直接App.js
から送っても動くが、初期の画面にもNavigatorを使うと遷移に一貫性が生まれて良い。
QiitaItemsListContainer.js
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
} from 'react-native';
import QiitaItemsListComponent from '../components/QiitaItemsListComponent';
const QIITA_URL
= "https://qiita.com/api/v2/tags/reactnative/items?page=1&per_page=8";
export default class QiitaItemsListContainer extends Component {
constructor(props) {
super(props);
this.state = {
items: null,
loaded: false,
}
}
componentDidMount() {
this.fetchData();
}
renderLoadingView() {
return (
<Text>
Loading Movies...
</Text>
);
}
fetchData() {
fetch(QIITA_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
items: responseData,
loaded: true,
});
})
.catch((error) => console.log(error));
}
render() {
return (
this.state.loaded ?
<QiitaItemsListComponent
data={this.state.items}
navigator={this.props.navigator}
/> :
this.renderLoadingView()
);
}
}
fetchしたデータをFlatListを持つコンポーネントに投げるだけのお仕事をするやつ。fetch終了時にloadedフラグを立てることでデータのロード終了を表現する。叩くAPIのURLのクエリにpage=1&per_page=8
と書いてあるのは、読み込みすぎてリクエスト制限かけられないようにするため(ホットリロードしてたら制限2回かけられた)なので好きに変えて良い。
QiitaItemsListComponent.js
import React, { Component } from 'react';
import {
StyleSheet,
FlatList,
} from 'react-native';
import QiitaItemComponent from './QiitaItemComponent';
export default class QiitaItemsListComponent extends Component {
constructor(props) {
super(props);
}
_keyExtractor = (item, index) => item.id;
render() {
const { data, navigator } = this.props;
return (
<FlatList
data={data}
extraData={data}
keyExtractor={this._keyExtractor}
renderItem={({ item }) =>
<QiitaItemComponent item={item} navigator={navigator} />}
style={styles.flatList}
/>
);
}
}
// 各種デザイン要素
var styles = StyleSheet.create({
flatList: {
backgroundColor: '#FFFFFF',
paddingTop: 44,
},
});
FlatListを表現するやつ。Navigatorをpropsで送ってもらわないとこの後のWebViewで泣く(泣いた)。
QiitaItemComponent.js
import React, { Component } from 'react';
import {
Text,
View,
Image,
StyleSheet,
TouchableWithoutFeedback,
} from 'react-native';
import QiitaItemViewComponent from './QiitaItemViewComponent';
export default class QiitaItemComponent extends Component {
constructor(props) {
super(props);
}
onPressed() {
const { item, navigator } = this.props;
navigator.push({
title: item.title,
component: QiitaItemViewComponent,
passProps: { url: item.url },
});
}
render() {
const { item } = this.props;
return (
<TouchableWithoutFeedback onPress={() => this.onPressed(item)}>
<View style={styles.item}>
<Image
source={{ uri: item.user.profile_image_url }}
style={styles.thumbnail} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.name}>{item.user.id}</Text>
</View>
</View>
</TouchableWithoutFeedback>
);
}
}
// 各種デザイン要素
var styles = StyleSheet.create({
item: {
borderWidth: 0.5,
},
rightContainer: {
flex: 1,
},
title: {
fontSize: 15,
margin: 8,
textAlign: 'left',
},
name: {
fontSize: 12,
margin: 8,
textAlign: 'left',
},
thumbnail: {
width: 80,
height: 80,
margin: 2,
},
});
FlatList内のItemを表現するやつ。デザインは全く考えていないので今度ちゃんと勉強したい。各記事がタップされたらWebViewが開くようになっている。
QiitaItemViewComponent.js
import React, { Component } from 'react';
import {
WebView,
} from 'react-native';
export default class QiitaItemViewComponent extends Component {
render() {
return (
<WebView
source={{ uri: this.props.url }}
/>
);
}
}
WebViewでQiitaの記事を見るやつ。WebViewにもStyleを指定できるようなのでいじってみたい。
App.js
import React from 'react';
import {
StyleSheet,
View,
} from 'react-native';
import RootNavigator from './navigators/RootNavigator';
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<RootNavigator />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
paddingTop: 33,
},
});
いつもの。
まとめ
React Nativeに関する記事を取ってみた。APIのURLを変更すれば好きなものを取れる(当然ユーザ側から指定できるようにしたい)。
結果は↓
少し手を加えればTwitterとかもできそう。Postもできるようになりたい。