inari111 blog

Webエンジニアの備忘録

React Native触ってみた

React NativeでQiitaの記事を表示してみた。
React NativeはReactjsベースでネイティブアプリを構築できるようなんだけど、Reactjsを書いたことがないのでチュートリアルと色々な人のコードを参考に書いてみた。
ほとんどhttp://qiita.com/y_matsuwitter/items/a7fc88e566b80b4c1eeaを参考にしました。
ありがとうございます。
備忘録として残します。

準備

基本的にはここを見ながらコマンド叩けば問題ない。

brew install node
npm install -g react-native-cli
react-native init ReactProject

これでプロジェクトが作成される。

.
├── ReactProject.xcodeproj
│   ├── project.pbxproj
│   └── xcshareddata
├── iOS
│   ├── AppDelegate.h
│   ├── AppDelegate.m
│   ├── Base.lproj
│   ├── Images.xcassets
│   ├── Info.plist
│   └── main.m
├── index.ios.js
├── node_modules
│   └── react-native
└── package.json

実行

ReactProject.xcodeprojをXcodeで開く。
Cmd+Rでビルドするとこのようになる。

f:id:tky-24:20150328205250p:plain

最初のビルドにXcodeを使うだけで、それ以降はシミュレーターでCmd+Rするだけ。

編集するファイルはindex.ios.js

QiitaのAPI叩いて、iosのタグがついたものを表示する。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
  NavigatorIOS,
  TouchableWithoutFeedback,
  WebView
} = React;

var REQUEST_URL = "https://qiita.com/api/v2/tags/iOS/items";

var ReactProject = React.createClass({
  render: function() {
    return (
      <NavigatorIOS
        style={styles.navigator}
        initialRoute={{
          component: QiitaList,
          title: 'iOS feed',
      }}/>
    );
  }
});

var QiitaList = React.createClass ({
  getInitialState: function() {
    return {
      items: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  },

  componentDidMount: function() {
    this.fetchData();
  },

  fetchData: function() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          items: this.state.items.cloneWithRows(responseData),
          loaded: true,
        });
      })
      .done();
  },

  render: function() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.items}
        renderRow={this.renderItem}
        style={styles.listView}
      />
    );
  },

  renderLoadingView: function() {
    return (
      <View style={styles.container}>
        <Text>
          Loading feed...
        </Text>
      </View>
    );
  },

  renderItem: function(item, sectionID, rowID) {
    return (
      <TouchableWithoutFeedback  onPress={() => this.onPressed(item)}>
      <View style={styles.container}>
        <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({
  navigator: {
  flex: 1
  },
  container: {
  flex: 1,
  flexDirection: 'row',
  justifyContent: 'center',
  alignItems: 'center',
  backgroundColor: '#FFFFFF',
  },
  rightContainer: {
  flex: 1,
  },
  title: {
  fontSize: 15,
  margin: 8,
  textAlign: 'left',
  },
  name: {
  fontSize: 12,
  margin: 8,
  textAlign: 'left',
  },
  thumbnail: {
  width: 80,
  height: 80,
  margin: 2,
  },
  listView: {
  backgroundColor: '#FFFFFF',
  },
});

AppRegistry.registerComponent('ReactProject', () => ReactProject);

とりあえず完成

記事を表示しただけなので、記事をタップしてWebVIew立ち上げるのはまだ実装してない。

f:id:tky-24:20150329194402p:plain

ハマったところ

ビルドしただけなのに
Invariant Violation: Application (Project-name) has not been registered.
とエラーが表示されることがあった。
どうやら、別の環境で起動したサーバーが動いたままになっているのが原因らしい。
Xcodeでビルドしたときに同時にTerminalも開くので、一度Controll + Cで終了させてから、もう一度ビルドするといい。

所感

  • 概要を把握したくらいなので、なんとも言えないが、個人的にはアリ
  • obj-c書くの辛い人は一部React Nativeで実装してもいいと思う
  • もっと細かいところまで勉強していきたい
  • Reactjsもやってみようと思う