Javascript ListFooter组件工作不正常?

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

我对平面列表有一个奇怪的问题, 当我向下滚动时,我从API获取数据,我增加页面+1,在页脚中,我呈现一个微调器,但当最后一页==当前页面时,这意味着没有数据,但微调器卡在底部,尽管我将其更新为false! 那这里怎么了

顺便说一句 当我在平面列表中这样调用renderFooter时

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;