LoginSignup
6
3

More than 5 years have passed since last update.

React NativeでTextInputを試してみた

Last updated at Posted at 2015-03-27

実際にチュートリアルをやってみて
http://facebook.github.io/react-native/docs/tutorial.html#content

入力に対して画面を変更するといったことをやってみたかったのでメモ
上記チュートリアルの Final source code から修正してみる

TextInputに入力した文字列で検索、Movieを絞り込む

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

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

var API_KEY = '7waqfqbprs7pajbz28mqf6vz';
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json';
var PAGE_SIZE = 25;
var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE;
var REQUEST_URL = API_URL + PARAMS;

var AwesomeProject = React.createClass({
  getInitialState: function() {
    return {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      movies: [],
      loaded: false,
      input: "",
    };
  },

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

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

  searchMovie: function(text) {
    var filteredMovies = this.state.movies.filter((movie) => movie.title.match(new RegExp(text, "i")))
    return this.setState({
      input: text,
      dataSource: this.state.dataSource.cloneWithRows(filteredMovies)
    });
  },

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

    return (
      <View>
        <TextInput style={styles.textInput} onChangeText={this.searchMovie} />
        <Text style={styles.text}>{this.state.input == "" ? "" : "Search: " + this.state.input}</Text>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderMovie}
          style={styles.listView}
        />
      </View>
    );
  },

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

  renderMovie: function(movie) {
    return (
      <View style={styles.container}>
        <Image
          source={{uri: movie.posters.thumbnail}}
          style={styles.thumbnail}
        />
        <View style={styles.rightContainer}>
          <Text style={styles.title}>{movie.title}</Text>
          <Text style={styles.year}>{movie.year}</Text>
        </View>
      </View>
    );
  },
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  rightContainer: {
    flex: 1,
  },
  title: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center',
  },
  text: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center',
    backgroundColor: '#FFFFFF'
  },
  year: {
    textAlign: 'center',
  },
  thumbnail: {
    width: 53,
    height: 81,
  },
  listView: {
    paddingTop: 20,
    backgroundColor: '#F5FCFF',
  },
  textInput: {
    marginTop: 20,
    height: 40,
    borderColor: 'gray',
    borderWidth: 1
  }
});

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

スクリーンショット 2015-03-27 14.06.00.png

APIで取ってきたデータを別途this.state.moviesに保存したが、
もしかしたらdataSourceから取得した方がいいのかもしれない

なんにせよthis.stateを変更するだけで、コードの見通しがよくなりそうなので
もう少しいろいろ試してみたい

6
3
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
6
3