2016-09-05 38 views
0

"のオブジェクトは反応する子として有効ではありません(見つかった:キー{日付、イベント}のオブジェクト)。代わりに配列を使用するか、ReactアドオンのcreateFragment(オブジェクト)を使用してオブジェクトをラップします.Viewのレンダリングメソッドを確認してください。エラー "反応するネイティブの

私は、メソッドコールのようなカスケードを持っています。私はその中のイベントで日付を取得しています。私はこれを正しくやっているように感じますが、上記のエラーが発生しています。私は場所でcreateFragmentを設定しようとしましたが、まだエラーが発生しています。コードは次のとおりです。

import React, { Component } from 'react'; 
    import { 
    AppRegistry, 
    Text, 
    View, 
    ScrollView, 
    RefreshControl, 
    StyleSheet, 
    Dimensions, 
    TextInput, 
    Linking, 
    TouchableNativeFeedback 
    } from 'react-native'; 

    var _ = require('lodash'); 
    var {width, height} = Dimensions.get('window'); 
    var renderif = require('render-if'); 
    var createFragment = require('react-addons-create-fragment'); 

    var IMAGES_PER_ROW = 1 

    class FunInATL extends Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
     currentScreenWidth: width, 
     currentScreenHeight: height, 
     dates: [], 
     boxIndex: 0, 
     showBox: false, 
     refreshing: false 
     }; 
    } 

     handleRotation(event) { 
      if (!this.state) { 
      return; 
      } 

      var layout = event.nativeEvent.layout 
      this.state({currentScreenWidth: layout.width, currentScreenHeight: layout.height }) 
     } 

     calculatedSize() { 
      var size = this.state.currentScreenWidth/IMAGES_PER_ROW 
      return {width: size} 
     } 

     renderRow(events) { 
      return events.map((events, i) => { 
      return (
       <Image key={i} style={[this.getImageStyles(), styles.image, this.calculatedSize() ]} source={{uri: event.image}} /> 
      ) 
      }) 
     } 

     openUrl(url) { 
      Linking.canOpenURL(url).then(supported => { 
       if (supported) { 
       Linking.openURL(url); 
       } else { 
       console.log('nope :: ' + url); 
       } 
      }).catch(err => console.error('An error occurred', err)); 
     } 

     getImageStyles(featured, category) { 
      let options = { 
       borderColor: 'gold', 
       borderWidth: featured ? 1 : 0 
      } 

      if (!category) { 
       options.height = featured ? 250 : 125 
      } 

      return options; 
     } 

     _clickImage(event, index) { 
      if (event.title) { 
      let new_val = !this.state.showBox 
      this.setState({ 
       dates: this.state.dates, 
       showBox: new_val, 
       boxIndex: new_val ? index : 0 
      }); 
      } 

     } 

     componentDidMount() { 
      this.state = { 
       dates: [], 
       boxIndex: 0, 
       showBox: false, 
       refreshing: false 
      }; 
      this.getApiData(); 

      Linking.addEventListener('url', this.handleUrl); 
     } 

     componentWillUnmount() { 
      Linking.removeEventListener('url', this.handleUrl); 
     } 

     getApiData() { 
      var _this = this; 
      return fetch('https://www.funinatl.com/mobile2.php?v1') 
      .then(function(response) { 
       return response.json() 
      }) 
      .then((responseJson) => { 
       var dates = createFragment(responseJson.events) 
       return; 

       let _this = this; 

       date.events.map((event, i) => (
       date.events[i] = event 
      )) 

       var datesData = []; 
       dates.map((date, i) => (
       datesData.push({ 
        date: i, 
        events: createFragment(date.events) 
       }) 
      )) 

       _this.setState({ 
       dates: createFragment(datesData), 
       boxIndex: 0, 
       showBox: false 
       }) 

       console.error(this.state); 
      }) 
      .catch((error) => { 
       console.error(error); 
      }) 
      .done(); 
     } 

     renderDates() { 
      return this.state.dates.map((date) => 
       (
        <View> 
        <Text style={styles.dateHeader}>{ date.date }</Text> 

        <View> 
        {this.renderEvents(date.events)} 
        </View> 
        </View> 

      )) 
     } 

     renderImage(event, index) { 
      if (this.state.showBox && this.state.boxIndex == index) { 
       return (
       <View> 
        <TouchableNativeFeedback onPress={()=>this._clickImage(event, index)}> 
         <Image source={{ uri: event.image }} style={[styles.image, this.calculatedSize(), this.getImageStyles(event.featured), { height: 100 }]} /> 
        </TouchableNativeFeedback> 
        <View style={{ flexDirection:'row', padding: 15 }}> 
         <Text style={styles.price}>{event.price}</Text> 
         <Text style={styles.time}>{event.time}</Text> 
         <TouchableNativeFeedback onPress={()=>this.openUrl(event.website)}> 
          <Text style={styles.btn}>Website</Text> 
         </TouchableNativeFeedback> 
        </View> 

         {renderif(event.venue)(
          <TouchableNativeFeedback onPress={()=>this.openUrl(event.venue)}> 
           <Text style={styles.btn}>Venue</Text> 
          </TouchableNativeFeedback> 
        )} 

       </View> 
      ) 
      } else { 
       return (
       <View> 
        <TouchableNativeFeedback onPress={()=>this._clickImage(event, index)}> 
         <Image source={{ uri: event.image }} style={[styles.image, this.calculatedSize(), this.getImageStyles(event.featured)]} /> 
        </TouchableNativeFeedback> 
       </View> 
      ) 
      } 
     } 

     renderEvents(events) { 
      return events.map((event, i) => 
      (
       <View> 
       <Text style={[styles.eventCategory, this.getImageStyles(event.featured, true)]}>{event.category}</Text> 
       <View> 
        {this.renderImage(event, i)} 
       </View> 
       <Text style={[styles.eventTitle, this.getImageStyles(event.featured, true)]}>{event.title}</Text> 
       </View> 
     )); 
     } 

     _onRefresh() { 
      this.setState({refreshing: true}); 
      fetchData().then(() => { 
      this.setState({refreshing: false}); 
      }); 
     } 

     render() { 
      return (
      <ScrollView onLayout={this.handleRotation} contentContainerStyle={styles.scrollView} refreshControl={ 
       <RefreshControl 
        refreshing={this.state.refreshing} 
        onRefresh={this._onRefresh.bind(this)} 
        tintColor="#ff0000" 
        title="Loading..." 
        titleColor="#00ff00" 
        colors={['#ff0000', '#00ff00', '#0000ff']} 
        progressBackgroundColor="#ffff00" 
       /> 
       }> 
       <Text style={styles.header}>FunInATL</Text> 
        {this.renderDates()} 
      </ScrollView> 
     ) 
     } 
     } 

    var styles = StyleSheet.create({ 

    row: { 
     flexDirection: 'row', 
     alignItems: 'center', 
     justifyContent: 'flex-start', 
     textAlign: 'center', 
     padding: 10 
    }, 

    header: { 
     fontSize: 30, 
     fontWeight: 'bold', 
     padding: 20, 
     textAlign: 'center', 
     backgroundColor: '#000', 
     color: '#fff' 
    }, 

    dateHeader: { 
     fontSize: 20, 
     fontWeight: 'bold', 
     padding: 20, 
     textAlign: 'left', 
     color: '#fff', 
     backgroundColor: '#283593' 
    }, 

    eventCategory: { 
     backgroundColor: '#03a9f4', 
     textAlign: 'center', 
     color: '#ffffff', 
     padding: 3 
    }, 

    eventTitle: { 
     borderTopWidth: 0, 
     textAlign: 'center', 
     fontWeight: 'bold', 
     padding: 3, 
     fontSize: 18, 
    }, 

    image: { 
    }, 

    btn: { 
     backgroundColor: 'green', 
     padding: 10, 
     color: '#fff', 
     textAlign: 'center', 
     flex: 1 
    }, 

    price: { 
     marginLeft: 10, 
     fontSize: 16, 
     flex: 1 
    }, 

    time: { 
     marginRight: 10, 
     fontSize: 16, 
     flex: 1, 
     width: 35 
    } 

    }); 

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

ありがとう!

EDIT:マップの提案ごとにコードが更新され、それでも動作しません。今は{イベント}について不平を言っています。

EDIT 2:フルコードで更新されました。

答えて

1

renderDates()などのコンポーネントのレンダーヘルパーは、_.each(...)を返します。​​は最初の引数を返します。そのため、エラーが発生します。

説明するために:

const myObject = { a: 1 }; 
_.each(myObject) === myObject // true 

を私はあなたの代わりにArray.prototype.map()を使用することをお勧め:

return this.state.dates.map((date) => (
    <View>...</View>   
)); 

私は上記の例で行ったようにあなたがarrow functionsを使用する場合は、thisへの参照を保存する必要はありません。 map()に渡された関数本体のthisは、コンポーネントのインスタンスにバインドされます。 getImageStyles()のような他のヘルパーメソッドをthis.getImageStyles(...)のように呼び出すことができます。

これは元の質問とは関係ありませんが、getApiData()メソッドは機能しません。あなたのような何かをresponseJsonを扱うチェーンの機能を置き換えることができます:あなたはまた、componentDidMount()this.state = {...}を削除する必要がある

(responseJson) => { 
    this.setState({ 
    dates: Object.entries(responseJson.events).map(([date, { events }]) => ({ 
     date, 
     events, 
    })), 
    boxIndex: 0, 
    showBox: false, 
    }); 
} 

warning in the docsには、「this.stateを直接変更しないでください。」と表示されています。

+0

上記の新しいコードで同じ問題が修正されました。今では代わりに{イベント}のためにそれを行います。 – charliepage88

+0

完全なコードを投稿してもよろしいですか? 'getApiData()'は 'undefined'を返します。私は 'createFragement()'が何であるかも分かりませんが、ここでは必要ありません。最後に、 'componentDidMount()'の 'this.state = {...}'を削除してください。 –

+0

完全なコードではなく、十分であると思っていましたが、私のindex.ios.jsファイルの内容を投稿しました – charliepage88

関連する問題