2015-05-15 10 views
6

Próbowałem uzyskać minimalny przykład nieskończonego przewijania. Więc mam to: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>); 
    } 
}); 

Gdybym przewinąć do samego dołu, onEndReached() jest zwolniony, ale nowe dane nie pojawia. Jakieś pomysły?

Odpowiedz

20

Zawsze sklonować swoje źródło danych z tymi samymi danymi, więc nowe nic się nie pojawia. Oto przykład roboczych (dodawanie nowych danych poprzez 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() nie natychmiast mutować this.state ale tworzy oczekiwaniu na przejście stanu. Dostęp do this.state po wywołaniu metody może potencjalnie zwrócić istniejącą wartość. Nie ma gwarancji synchronicznej obsługi wywołań setState, a wywołania mogą być grupowane od w celu zwiększenia wydajności.

więc problemów jest tutaj

this.setState({ 
     isLoadingTail: true 
    }); 

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

Odpowiedz przez @vkurchatkin jest lepszy i to zdecydowanie rozwiązuje problem. Ale w każdym razie kod, który wskazałem, jest zepsuty. Komponent nie będzie ponownie renderować po każdym setState –

+1

w jaki sposób to może odpowiedzieć na pytanie? –

+0

Nie sądzę, że w tamtym czasie nie miałem wystarczająco dużo karmy, aby zamieszczać komentarze, więc napisałem odpowiedź. –

0

Szukałem tego rozwiązania na bardzo długi czas. Wreszcie wpadłem na tej biblioteki wagi lekkiej: -

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} 
/>