Javascript ListFooter组件工作不正常?
我对平面列表有一个奇怪的问题, 当我向下滚动时,我从API获取数据,我增加页面+1,在页脚中,我呈现一个微调器,但当最后一页==当前页面时,这意味着没有数据,但微调器卡在底部,尽管我将其更新为false! 那这里怎么了 顺便说一句 当我在平面列表中这样调用renderFooter时Javascript ListFooter组件工作不正常?,javascript,reactjs,react-native,react-native-flatlist,Javascript,Reactjs,React Native,React Native Flatlist,我对平面列表有一个奇怪的问题, 当我向下滚动时,我从API获取数据,我增加页面+1,在页脚中,我呈现一个微调器,但当最后一页==当前页面时,这意味着没有数据,但微调器卡在底部,尽管我将其更新为false! 那这里怎么了 顺便说一句 当我在平面列表中这样调用renderFooter时 ListFooterComponent={()=> this._renderFooter()} // it disappeare the bottom spiner if last page == curren
ListFooterComponent={()=> this._renderFooter()} // it disappeare the bottom spiner if last page == current page but I have an unexpected re-rendering and app laggay and in some time spinner disappeared even I scrolling to bottom!!
代码
类lastComponent.PureComponent{
构造函数(){
超级();
此.state={
歌曲:[],
加载:false,
页码:1,
最后一页:1,
};
this.isCancelled=false;
}
操纵器阵列=异步(阵列)=>{
让歌曲=[];
array.map((轨迹)=>
歌曲。推({
id:track.id,
名称:track.name,
url:url+track.sounds,
img:URL+track.avatar,
}),
);
返回歌曲;
};
getData=async()=>{
试一试{
this.setState({loading:true});
让response=wait-API.get(`/tracks?page=${this.state.page}`);
让lastPage=response.data.data.items.last_页面;
让{
数据:{
数据:{
项目:{data},
},
},
}=响应;
让所有的歌曲都等待这一刻;
这是我的国家({
歌曲:this.state.songs.concat(所有歌曲),
最后一页:最后一页,
});
}捕捉(错误){
console.log('err',err);
}
};
_renderItems=({item,index})=>(
{
this.props.saveSongs(this.state.songs,索引);
这个.props.isplay(true);
this.props.isPauseTrigger(!this.props.isPauseTrigger);
}}
背景={TouchableNativeFeedback.Ripple('white')}
delayPressIn={0}
使用前景>
{item.name}
);
handleLoadMore=()=>{
如果(this.state.page
设置超时(()=>{
这是getData();
}, 800),
);
}else if(this.state.page==this.state.last_页){
this.setState({loading:false},()=>
log('if--loading',this.state.loading),
);
}
};
_renderFooter=()=>{
是否返回此.state.loading(
):null;
};
componentDidMount(){
这是getData();
}
_keydextractor=(song)=>song.id;
_renderListEmptyComponent=()=>;
render(){
log('apprerender!');
返回(
this.props.navigation.goBack()}>
اخر الاغاني
);
}
}
const mapDispatchToProps=(调度)=>{
返回{
isPlaying:(_isPlaying)=>{
调度(iPlayingAction(_iPlaying));
},
isPauseTrigger:(_isPause)=>{
调度(isPauseAction(_isPause));
},
保存歌曲:(歌曲,索引)=>{
调度(saveSongsPlayer(歌曲、索引));
},
};
};
导出默认连接(null,mapDispatchToProps)(LastSongs);
当您滚动到底部时,您正在调用一个带有超时的异步函数。该超时将覆盖以下代码,并再次将加载设置为true。因此,在这种情况下,加载永远不会是错误的
} else if (this.state.page === this.state.last_page) {
this.setState({loading: false}, () =>
console.log('if--loading', this.state.loading), // log false!! that's mean a spinner should disapeare
);
}
你需要两样东西
1) 在catch块中尝试将加载设置为false
} catch (err) {
console.log('err', err);
this.setState({loading: false});
}
2) 在您的状态中添加另一个初始值为false的值isAllDataFetched
。从API接收空数据时,将加载设置为false。不确定你的数据是什么样子的,但做一些类似的事情
getData = async () => {
try {
this.setState({loading: true});
let response = await API.get(`/tracks?page=${this.state.page}`);
let lastPage = response.data.data.items.last_page;
let {
data: {
data: {
items: {data},
},
},
} = response;
// if it's an array
if(data.length === 0) {
this.setState({loading: false, isAllDataFetched: true});
}
//...
} catch (err) {
console.log('err', err);
}
};
最后,在handleLoadMore方法中添加以下行
handleLoadMore = () => {
if(this.state.isAllDataFetched) return;
我为你制作了一个演示。你可以按照这个逻辑去做。这和你的有点不同,但我认为会有帮助 这是代码
import React from 'react';
import {
View, Text, FlatList, ActivityIndicator, SafeAreaView
} from 'react-native';
class App extends React.PureComponent {
state = {
songs: [
{
userId: 1,
id: 1,
title: 'delectus aut autem 1',
completed: false,
},
{
userId: 1,
id: 2,
title: 'delectus aut autem 2',
completed: false,
},
],
loading: false,
page: 3,
totalPage: 10,
};
componentDidMount() {
this.getData();
}
getData = async () => {
const { songs } = this.state;
try {
this.setState({ loading: true });
const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${this.state.page}`, {
headers: {
'Content-Type': 'application/json',
},
});
const json = await response.json();
this.setState({
songs: [...songs, json],
});
this.setState({ loading: false });
} catch (err) {
console.log('err', err);
this.setState({ loading: false });
}
};
renderItems = ({ item }) => (
<Text style={{ backgroundColor: 'blue', height: 200, marginBottom: 5 }}>{`${item.title}-${item.id}`}</Text>
);
onEndReached = () => {
const { page, loading, totalPage } = this.state;
if (loading) return;
if (page <= totalPage) {
this.setState({ loading: true, page: page + 1 }, () =>
setTimeout(() => {
this.getData();
}, 2000));
} else {
this.setState({ loading: false });
}
}
renderFooter = () => {
const { loading } = this.state;
if (loading) {
return (
<View>
<ActivityIndicator color="#000" size="large" />
</View>
);
}
return null;
}
renderListEmptyComponent = () => <View />;
render() {
const { songs } = this.state;
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'red' }}>
<FlatList
data={songs}
keyExtractor={song => song.id}
initialNumToRender={10}
contentContainerStyle={{ flexFrow: 1, backgroundColor: 'white' }}
style={{ flex: 1 }}
ListEmptyComponent={this.renderListEmptyComponent}
renderItem={this.renderItems}
onEndReached={this.onEndReached}
onEndReachedThreshold={0.7}
ListFooterComponent={this.renderFooter}
/>
</SafeAreaView>
);
}
}
export default App;
从“React”导入React;
进口{
视图、文本、平面列表、活动指示器、安全区域视图
}从“反应本机”;
类App扩展了React.PureComponent{
状态={
歌曲:[
{
用户ID:1,
id:1,
标题:'deletus aut autem 1',
已完成:错误,
},
{
用户ID:1,
id:2,
标题:'deletus aut autem 2',
已完成:错误,
},
],
加载:false,
页码:3,
总页数:10,
};
componentDidMount(){
这是getData();
}
getData=async()=>{
const{songs}=this.state;
试一试{
this.setState({loading:true});
const response=等待获取(`https://jsonplaceholder.typicode.com/todos/${this.state.page}`{
标题:{
“内容类型”:“应用程序/json”,
},
});
const json=await response.json();
这是我的国家({
歌曲:[……歌曲,json],
});
this.setState({loading:false});
}捕捉(错误){
console.log('err',err);
this.setState({loading:false});
}
};
renderItems=({item})=>(
{`${item.title}-${item.id}`}
);
onEndReached=()=>{
const{page,loading,totalPage}=this.state;
如果(装载)返回;
如果(第页)
设置超时(()=>{
这是getData();
}, 2000));
}否则{
this.setState({loading:false});
}
}
renderFooter=()=>{
const{loading}=this.state;
如果(装载){
返回(
(使用iOS设备)我得到了一个对象数组,并且我已经在初始状态下将数据设置为空,因此我猜isAllDataFetched在这里没有意义!handleLoadMore像我对你的line if语句所做的那样保留它?我正在尝试你的方法,但遗憾的是,我遇到了同样的问题;(请再次检查问题,我将其添加。你解决问题了吗?添加了演示,希望对您有所帮助。
import React from 'react';
import {
View, Text, FlatList, ActivityIndicator, SafeAreaView
} from 'react-native';
class App extends React.PureComponent {
state = {
songs: [
{
userId: 1,
id: 1,
title: 'delectus aut autem 1',
completed: false,
},
{
userId: 1,
id: 2,
title: 'delectus aut autem 2',
completed: false,
},
],
loading: false,
page: 3,
totalPage: 10,
};
componentDidMount() {
this.getData();
}
getData = async () => {
const { songs } = this.state;
try {
this.setState({ loading: true });
const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${this.state.page}`, {
headers: {
'Content-Type': 'application/json',
},
});
const json = await response.json();
this.setState({
songs: [...songs, json],
});
this.setState({ loading: false });
} catch (err) {
console.log('err', err);
this.setState({ loading: false });
}
};
renderItems = ({ item }) => (
<Text style={{ backgroundColor: 'blue', height: 200, marginBottom: 5 }}>{`${item.title}-${item.id}`}</Text>
);
onEndReached = () => {
const { page, loading, totalPage } = this.state;
if (loading) return;
if (page <= totalPage) {
this.setState({ loading: true, page: page + 1 }, () =>
setTimeout(() => {
this.getData();
}, 2000));
} else {
this.setState({ loading: false });
}
}
renderFooter = () => {
const { loading } = this.state;
if (loading) {
return (
<View>
<ActivityIndicator color="#000" size="large" />
</View>
);
}
return null;
}
renderListEmptyComponent = () => <View />;
render() {
const { songs } = this.state;
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'red' }}>
<FlatList
data={songs}
keyExtractor={song => song.id}
initialNumToRender={10}
contentContainerStyle={{ flexFrow: 1, backgroundColor: 'white' }}
style={{ flex: 1 }}
ListEmptyComponent={this.renderListEmptyComponent}
renderItem={this.renderItems}
onEndReached={this.onEndReached}
onEndReachedThreshold={0.7}
ListFooterComponent={this.renderFooter}
/>
</SafeAreaView>
);
}
}
export default App;