2016-06-20 1 views
1

私は、リストの最初の要素が「追加」ボタンであるグリッドとして画像のリストを表示するアプリケーションを持っています。私はまた、すべての画像をTouchableにする必要があります。現在、私のコードは次のようになります場合、誰かに異なるコールバックを持つTouchableOpacityアイテムのグリッドを作成する最も良い方法は?

class RNtest extends Component { 
    constructor() { 
     super(); 

     this.state = { 
      data: [], 
      counter: 0 //Used to give unique numbers to the items 
     }; 
    } 

    itemPicker() { 
     var temp = this.state.data; 
     temp.push({text: this.state.counter}); 
     this.setState({ 
      data: temp, 
      counter: this.state.counter + 1 
     }); 
    } 

    onPress() { 
     console.warn('YO!'); 
    } 

    render() { 
     return (
      <ScrollView style={styles.body}> 

       <View style={styles.section}> 
        <Text style={styles.sectionHeader}>ITEMS</Text> 

        <View style={styles.gallery}> 
         <TouchableOpacity 
          style={styles.addButton} 
          onPress={this.itemPicker.bind(this)} 
         > 
          <Text>ADD</Text> 
         </TouchableOpacity> 

         {this.state.data.map(function(item) { 
          return (
           <TouchableOpacity 
            style={styles.item} 
            onPress={this.onPress.bind(this)} 
           > 
             <Text>{item.text}</Text> 
           </TouchableOpacity> 
          ); 
         })} 
        </View> 
       </View> 

      </ScrollView> 
     ); 
    } 

} 

スタイルシート、それを必要とします:

var styles = StyleSheet.create ({ 
    addButton: { 
     alignItems: 'center', 
     justifyContent: 'center', 
     height: 72, 
     width: 72, 
     borderRadius: 2, 
     marginVertical: 6, 
     marginRight: 6, 
     backgroundColor: 'white' 
    }, 
    gallery: { 
     flexDirection: 'row', 
     flexWrap: 'wrap' 
    }, 
    item: { 
     alignItems: 'center', 
     justifyContent: 'center', 
     backgroundColor: '#DCFFC2', 
     height: 72, 
     width: 72, 
     borderRadius: 2, 
     margin: 6 
    }, 
    section: { 
     flexDirection: 'column', 
     paddingTop: 10 
    }, 
    sectionHeader: { 
     fontSize: 13, 
     fontWeight: '400', 
     paddingBottom: 1, 
     color: '#A7A7A7' 
    }, 
    body: { 
     flex: 1, 
     backgroundColor: '#EEEEEE', 
     paddingVertical: 10, 
     paddingHorizontal: 20 
    }, 
}); 

明らかthisは、forループ内の表示されていないので、当然たonPress機能が動作しません。

私はListViewを使用することができましたが、renderRowの内部では、レンダリングするアイテムが追加ボタンであるかどうかを確認しなければならず、いくつかの他の部分も同様に難しくなります。

このような状況では、私は参考文献を使用することができますか?いいですか?

私はAndroidエミュレータでReact Native 0.27.2を実行しています。

答えて

2

現時点で問題がスコープに関連している場合は、this.state.dataを処理するmap関数のスコープを指定することで最も適切に修正できます。しかし、私はあなたのコードにコメントするためのいくつかの他の問題を参照してください。

  1. あなたitemPicker機能は直接push機能を経由して、あなたの状態を突然変異されます。 concatなどの新しい配列(またはスプレッド演算子)を返す関数を使用することを選択します。このように状態を直接変更しないようにする理由は、docsを参照してください。

    import React, { Component } from 'react'; 
    import { 
        ScrollView, 
        StyleSheet, 
        Text, 
        TouchableOpacity, 
        View 
    } from 'react-native'; 
    
    class RNTest extends Component { 
        constructor(props) { 
         super(props); 
    
         this.state = { 
          data: [], 
          counter: 0 
         }; 
        } 
    
        itemPicker() { 
         // 'push' will mutate, concat will return a new array 
         this.setState({ 
          data: this.state.data.concat({text: this.state.counter}), 
          counter: this.state.counter + 1 
         }); 
        } 
    
        createButton (item, index) { 
         // add a unique key, per react warnings 
         return (
          <TouchableOpacity 
           key={index} 
           style={styles.item} 
           onPress={this.onPress}> 
            <Text>{item.text}</Text> 
          </TouchableOpacity> 
         ); 
        } 
    
        onPress() { 
         console.warn('YO!'); 
        } 
    
        render() { 
         return (
          <ScrollView style={styles.body}> 
    
           <View style={styles.section}> 
            <Text style={styles.sectionHeader}>ITEMS</Text> 
    
            <View style={styles.gallery}> 
             <TouchableOpacity 
              style={styles.addButton} 
              onPress={this.itemPicker.bind(this)} 
             > 
              <Text>ADD</Text> 
             </TouchableOpacity> 
    
             {this.state.data.map(this.createButton, this)} 
            </View> 
           </View> 
    
          </ScrollView> 
         ); 
        } 
    
    } 
    
    export default RNTest; 
    

  2. は、私はこれらの概念を実証するために、あなたのコードサンプルを変更した(リアクトからの警告を参照してください)

をあなたが作成している結果TouchableOpacityアイテムにユニークなkeyを追加していることを確認します

+0

ありがとう、これは美しく動作します。私はReact Nativeで多くの経験を積んでいないので、他の間違いを指摘してくれてうれしいです。 –

0

は矢印の機能を使用してみてください:

{this.state.data.map((item) => { 
    // your code 
})} 

それとも、bindを使用することができます。

{this.state.data.map(function(item) { 
    return (
     <TouchableOpacity 
      style={styles.item} 
      onPress={this.onPress.bind(this)} 
     > 
     <Text>{item.text}</Text> 
     </TouchableOpacity> 
    ); 
}.bind(this))} 

両方のソリューションは、あなたのループ内にthisパラメータを渡してくださいどのような。

関連する問題