2015-05-15 53 views
6

Ho cercato di ottenere un esempio minimo di scroll infinito. Così ho questo:React Native Infinite Scroll

var React = require('react-native'); 

var { 
    StyleSheet, 
    View, 
    Image, 
    ListView, 
    } = React; 

var data = [ 
    { 
     "id": 1, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 2, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 3, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 4, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 5, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 6, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    } 

]; 

var InfiniteScreen = React.createClass({ 
    getInitialState: function() { 
     return { 
      isLoadingTail: false, 
      dataSource: new ListView.DataSource({ 
       rowHasChanged: (row1, row2) => row1 !== row2, 
      }) 
     }; 
    }, 
    componentDidMount: function() { 
     this.setState({ 
      dataSource: this.getDataSource(data) 
     }); 
    }, 
    renderRow: function (item) { 
     return (
      <View> 
       <Image style={{width: 80, height: 80}} source={{uri: 'http:' + item.profile_picture.href}}/> 
      </View> 
     ); 
    }, 
    onEndReached: function() { 
     console.log('onEndReached', this.state.isLoadingTail); 
     if (this.state.isLoadingTail) { 
      // We're already fetching 
      return; 
     } 
     this.setState({ 
      isLoadingTail: true 
     }); 

     this.setState({ 
      isLoadingTail: false, 
      dataSource: this.getDataSource(data) 
     }); 
    }, 
    getDataSource: function (users):ListView.DataSource { 
     return this.state.dataSource.cloneWithRows(users); 
    }, 
    render: function() { 
     return (
      <View> 
       <ListView 
        dataSource={this.state.dataSource} 
        renderRow={this.renderRow} 
        onEndReached={this.onEndReached} 
       /> 
      </View>); 
    } 
}); 

Se ho scorrere fino in fondo, onEndReached() è sparato, ma i nuovi dati non viene visualizzato. Qualche idea?

risposta

20

È sempre clonare l'origine dati con gli stessi dati, in modo nuovo appare nulla. Ecco un esempio di lavoro (aggiungere nuovi dati tramite concat):

var React = require('react-native'); 

var { 
    StyleSheet, 
    View, 
    Image, 
    ListView, 
    } = React; 

var data = [ 
    { 
     "id": 1, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 2, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 3, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 4, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 5, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    }, 
    { 
     "id": 6, 
     "profile_picture": { 
      "href": "//like1.r.worldssl.net/ui_big/1305634.jpg" 
     } 
    } 

]; 

var InfiniteScreen = React.createClass({ 
    getInitialState: function() { 
     return { 
      isLoadingTail: false, 
      dataSource: new ListView.DataSource({ 
       rowHasChanged: (row1, row2) => row1 !== row2, 
      }) 
     }; 
    }, 
    componentDidMount: function() { 
     this._data = []; 
     this.setState({ 
      dataSource: this.getDataSource(data) 
     }); 
    }, 
    renderRow: function (item) { 
     return (
      <View> 
       <Image style={{width: 80, height: 80}} source={{uri: 'http:' + item.profile_picture.href}}/> 
      </View> 
     ); 
    }, 
    onEndReached: function() { 
     console.log('onEndReached', this.state.isLoadingTail); 
     if (this.state.isLoadingTail) { 
      // We're already fetching 
      return; 
     } 
     this.setState({ 
      isLoadingTail: true 
     }); 

     this.setState({ 
      isLoadingTail: false, 
      dataSource: this.getDataSource(data) 
     }); 
    }, 
    getDataSource: function (users):ListView.DataSource { 
     this._data = this._data.concat(users); 
     return this.state.dataSource.cloneWithRows(this._data); 
    }, 
    render: function() { 
     return (
      <View style={styles.container}> 
       <ListView 
        dataSource={this.state.dataSource} 
        renderRow={this.renderRow} 
        onEndReached={this.onEndReached} 
       /> 
      </View>); 
    } 
}); 

var styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    justifyContent: 'center', 
    backgroundColor: '#F5FCFF', 
    }, 
}); 
0

https://facebook.github.io/react/docs/component-api.html#setstate

setState() non abbia immediatamente mutano this.state ma crea una transizione di stato sospeso. L'accesso a this.state dopo aver chiamato questo metodo può potenzialmente restituire il valore esistente. Non è disponibile la garanzia del funzionamento sincrono delle chiamate su setState e le chiamate possono essere in batch per i guadagni di prestazioni.

così i problemi è qui

this.setState({ 
     isLoadingTail: true 
    }); 

    this.setState({ 
     isLoadingTail: false, 
     dataSource: this.getDataSource(data) 
    }); 
+2

Risposta da @vkurchatkin è migliore e si risolve definitivamente il problema. Ma, comunque, il codice che ho indicato è rotto. Il componente non verrà re-renderizzato dopo ogni setState –

+1

come questo può rispondere alla domanda? –

+0

Non è così, immagino che in quel momento non avevo abbastanza karma per postare commenti, quindi ho postato una risposta. –

0

Ho cercato per questa soluzione per molto tempo. Infine mi si avvicinò con questa libreria peso leggero: -

https://www.npmjs.com/package/rn-infinite-scroll

import InfiniteListView from 'rn-infinite-scroll'; 

<InfiniteListView 
    data ={this.state.items} 
    renderRow={this.renderRow} 
    canLoad={this.canLoad()} 
    isLoading={this.state.isLoading} 
    onLoad={this.onLoad} 
/>