2016-08-16 6 views
0

componentWillReceivePropsが実行されるときにリストビューを更新しようとしています。これは、取得後にdataSourceが更新されたようです(console.log(this.state.dataSource)をrender()に入れ、エンドポイントの現在のステータスに従って変更します)。componentWillReceivePropsの後にdataSourceが更新されますが、リストビューは反応ネイティブでリフレッシュされません。

ただし、ListViewはそのままです。私はなぜ疑問に思っていたし、dataSourceの疑いがありました。だから私はrender()内のdataSourceを出力するためにstringオブジェクトを作成しました。 var str = JSON.stringify(this.state.dataSource._dataBlob.s1);

そして<View><Text>{str}</Text>

上記一部変更componentWillReceiveProps()が実行されたとき。ただし、リストビューは同じままです。私はこれがなぜ起こるのかを知りません。

ここに私のコードのスニペットがあります。

componentWillReceiveProps(){ 
    var query = ApiUrl.urlForWeekInfo(this.state.email); 
    console.log(query); 
    this._executeQuery(query,3); 
    } 


    constructor(props) { 
    super(props); 

    var dataSource = new ListView.DataSource(
     {rowHasChanged: (r1, r2) => r1.guid !== r2.guid}); 

     this.state = { 
     isLoading: false, 
     ... 
     first_name: this.props.first_name, 
     email: this.props.email, 
     dataSource: dataSource.cloneWithRows(this.props.listings)  
    }; 
    } 
.. 

_executeQuery(query,i) { 

    this.setState({ isLoading: true }); 
    fetch(query) 
     .then(response => response.json()) 
     .then(json => this._handleResponse(json.response,i)) 
     .catch(error => 
     this.setState({ 
      isLoading: false, 
      message: 'Something bad happened ' + error 
    })); 
    } 

    _handleResponse(response,i) { 
    this.setState({ isLoading: false , message: '' }); 
    if (response.application_response_code.substr(0, 1) === '1') { 
     if(i==1){ 
     this.props.navigator.push({ 
      title: 'Apply', 
      component: Apply, 
      passProps: {listings: response.listings, times: response.timetable, week_num: this.state.week_num} 
     }); 
     } else if (i==3){ 

     var output = response.listings; 
     this.setState({ 
      dataSource: this.state.dataSource.cloneWithRows(output) 
     }); 

     console.log(response.listings); 
     this.forceUpdate(); 

     } 
    } else { 
    } 
    } 

render() { 

    console.log(this.state.dataSource._dataBlob.s1); 

    var str = JSON.stringify(this.state.dataSource._dataBlob.s1); 
    var listviewsource = this.state.dataSource; 

    return (

    <View style={[this.border('red'), styles.container_top]}> 
     <View style={[this.border('black'), styles.container_top_buttons]} > 

     <ListView 
      dataSource={listviewsource} 
      renderRow={this.renderRow.bind(this)}/> 

     </View>  
     {spinner} 
     <View> 
     <Text>{str}</Text> 
     </View> 

    </View> 




     ); 
     }} 

ご意見やご経験があれば教えてください。


私はこの問題の解決策を見つけることになった:

var array = response.listings; 
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); 
    //=> call another ds variable. 

    this.setState({ 
     rawData: array, 
     dataSource: ds.cloneWithRows(response.listings) 
    }); 

答えて

1

あなたのListViewに行を更新する直接的な方法はありません。そこにListView.DataSourceの多くの文書はありません。だからここではSETSTATE中)(追加/追加/先頭に追加/更新/リストビューから行を削除したい場合は、あなたがしなければならないすべてはただのdataSourceを更新し、cloneWithRowsを呼び出している

をgoes-。

たとえば、 URLからデータを取得したい私が「もっと読み込み」を押すたびに、データソースに新しい行を追加します。非常に最初の時間で

getInitialState: function(){ 
    return { 
     rawData: [], 
     dataSource: new ListView.DataSource({ 
      rowHasChanged: (row1, row2) => row1 !== row2 
     }), 
     loaded: false, 
     page: 1, 
    } 
}, 

、私は(ComponentDidMountでこの関数を呼び出す)状態での初期データと、「ページ」= 1で私のリストビューを移入しました。

reloadData: function(){ 
    this.setState({ loaded: false, rawData: [], page: 1 }); 

    API.getUpcomingMovies(this.state.page) 
     .then((data) => { 
      this.setState({ 
      rawData: this.state.rawData.concat(data), 
      dataSource: this.state.dataSource.cloneWithRows(this.state.rawData.concat(data)), 
      loaded: true, 
      }); 
     }); 
    }, 

そして、APIからJSONを取得するために「もっと読み込み」をタップするたびに、次の関数を呼び出します。私が「もっと読み込み」を押すたびに「ページ」がインクリメントされます。

ご覧のとおり、rawData [](JSONオブジェクトを保持する単純な配列)を連結しています。あなたのrawDataに新しいデータを追加する場合は、次のようなことができます。

this.setState({ 
    rawData: data.concat(this.state.rawData) 
)} 
+0

私の場合は、連結したり前に付ける必要はありませんが、すべてをすべてリロードします。 cloneWithRows文でdataSourceに触れたとしても、それは私のためには機能しませんでした。私は '新しいListView'を使用しようとした、それは動作するようになります!あなたはそのようなやり方をすることに否定的な側面を示唆しますか? –

+0

@SungpahLee何も本当に!あなたがしたことは、私のスニペットと本質的に同じです。私は 'getInitialState()'に '新しいListView'を持っていて、あなたは' constructor() 'で同じものを持っています。だからIMO私はこのアプローチの欠点は見当たりません。しかし、他の見解を歓迎します。また、連結の代わりにデータを直接置き換えることもできます。これらの基本的な操作よりも、Gistは重要です。データを再レンダリングする場合は、 'cloneWithRows(newdata)'を呼び出してstate.dataSourceを更新するだけで済みます。 – Mihir