LoginSignup
1
0

More than 5 years have passed since last update.

React NativeでQiitaクライアントアプリを作りたい人生だった

Last updated at Posted at 2018-06-02

はじめに

新卒エンジニア2ヶ月目。
Webやネイティブに関する知識は全く無かったのでいろんなものを参考に自分でも作ってみる。

Qiitaのクライアントアプリ作れたら面白そうだなと思ったので調べたら似たような(というかほぼやりたいこと)記事https://qiita.com/y_matsuwitter/items/a7fc88e566b80b4c1eeaがあった。ES5以前に書かれているようだったので自分なりにES6バージョンにしてみた。

コードについて

GitHubにも上げてあるhttps://github.com/Ikeponias/qiita-client

RootNavigator.js

navigator/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

container/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

component/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

component/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

component/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

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を変更すれば好きなものを取れる(当然ユーザ側から指定できるようにしたい)。
結果は↓
スクリーンショット 2018-05-27 14.25.44.png

少し手を加えればTwitterとかもできそう。Postもできるようになりたい。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0