React Native 无限滚动
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>);
}
});
如果我滚动到最底部,将触发 onEndReached(),但不会显示新数据。有什么想法吗?
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.
所以问题就在这里
this.setState({
isLoadingTail: true
});
this.setState({
isLoadingTail: false,
dataSource: this.getDataSource(data)
});
您总是使用相同的数据克隆您的数据源,因此不会出现任何新内容。这是一个工作示例(通过 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',
},
});
我一直在寻找这个解决方案。最后我想出了这个轻量级库 :-
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}
/>
ListView is currently Deprecated. You will have to use FlatList or SectionList. You can find an example of infinite scroll using FlatList in this answer for another question. 。
我试图获得无限滚动的最小示例。 所以我有这个:
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>);
}
});
如果我滚动到最底部,将触发 onEndReached(),但不会显示新数据。有什么想法吗?
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.
所以问题就在这里
this.setState({
isLoadingTail: true
});
this.setState({
isLoadingTail: false,
dataSource: this.getDataSource(data)
});
您总是使用相同的数据克隆您的数据源,因此不会出现任何新内容。这是一个工作示例(通过 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',
},
});
我一直在寻找这个解决方案。最后我想出了这个轻量级库 :-
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}
/>
ListView is currently Deprecated. You will have to use FlatList or SectionList. You can find an example of infinite scroll using FlatList in this answer for another question. 。