javascript 反应原生无限滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30262404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React Native Infinite Scroll
提问by Ladislav M
I've tried to get a minimal example of infinite scroll. So I have this:
我试图得到一个无限滚动的最小例子。所以我有这个:
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>);
}
});
If I scroll to the very bottom, onEndReached() is fired, but the new data doesn't appear. Any ideas?
如果我滚动到最底部,onEndReached() 会被触发,但不会出现新数据。有任何想法吗?
回答by vkurchatkin
You always clone your data source with the same data, so nothing new appears. Here is a working example (add new data via concat
):
您始终使用相同的数据克隆数据源,因此不会出现任何新内容。这是一个工作示例(通过添加新数据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',
},
});
回答by Liubomyr Mykhalchenko
https://facebook.github.io/react/docs/component-api.html#setstate
https://facebook.github.io/react/docs/component-api.html#setstate
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。无法保证对 setState 调用的同步操作,并且可能会批量调用以提高性能。
so the problems is here
所以问题就在这里
this.setState({
isLoadingTail: true
});
this.setState({
isLoadingTail: false,
dataSource: this.getDataSource(data)
});
回答by Aditya Agrawal
I've been looking for this solution for very long time. Finally I came up with this light weight library :-
我一直在寻找这个解决方案很长一段时间。最后我想出了这个轻量级的库:-
https://www.npmjs.com/package/rn-infinite-scroll
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}
/>
回答by Haseeb Eqx
ListViewis currently Deprecated. You will have to use FlatListor SectionList. You can find an example of infinite scroll using FlatList in this answer for another question. https://stackoverflow.com/a/47710224/7477198.
ListView目前已弃用。您将不得不使用FlatList或SectionList。您可以在另一个问题的答案中找到使用 FlatList 的无限滚动示例。https://stackoverflow.com/a/47710224/7477198。