【问题标题】:React native List View onEndReached calling multiple times反应原生列表视图 onEndReached 多次调用
【发布时间】:2016-12-23 07:29:05
【问题描述】:

我在 react native 中使用列表视图 onEndReached 组件时遇到了一些问题。

渲染代码:

@autobind
  _fetchMoreHistory(){

    console.log("Fetch more history called");

  }

<View style={[styles.Ctr]}>
   <ListView dataSource={this.state.txHistorySource}
         renderRow={ this._renderRow }
         onEndReached ={ this._fetchMoreHistory }
         onEndReachedThreshold  = {10}/>
</View>

我打开屏幕的那一刻_fetchMoreHistory 被调用了两次并且在onEndReached 到达之后正常工作。有人可以帮忙调试吗?

【问题讨论】:

标签: javascript reactjs react-native


【解决方案1】:

我遇到了同样的问题并搜索了很多但没有找到任何答案,所以我使用条件来检查第一个请求是否获得了我再次触发的数据,否则我没有

示例 // onEndReached 如果(条件){ 拨打电话 }

【讨论】:

    【解决方案2】:

    所以我的解决方案很简单。根本不要使用onEndReached。使用onScroll 并检测滚动结束。

    isCloseToBottom = ({ layoutMeasurement, contentOffset, contentSize }) => { const paddingToBottom = 20; // how far from the bottom return layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom; };

    FlatList 组件

     <FlatList      
          data={data}        
           onScroll={({ nativeEvent }) => {
              if (this.isCloseToBottom(nativeEvent)) {
                // Dont forget to debounce or throttle this function.
                this.handleOnEndReached();
              }
           }}
      />
    

    【讨论】:

    • 糟糕的方法。这将被多次调用。
    • 这就是我在那里添加评论的原因(不要忘记去抖动或限制此功能。)
    • 评论没有改变任何东西。这不是它的完成方式。
    【解决方案3】:

    我有同样的问题。但我发现我有包裹我的FlatListScrollView。 当我删除它时,一切都开始正常工作。

    很遗憾,官方文档中没有提到这一点

    【讨论】:

    • 这对于那些将 flatlist 包裹在 scrollView 中的人来说应该是正确的答案
    【解决方案4】:

    我通过创建一个告诉我服务是否正在加载的状态变量解决了这个问题。

    class Component1 extends Component {
    public constructor(props) {
        super(props);
    
        this.state = {
            isLoading: false,
            listOfItems: []
        };
    }
    
    public componentDidMount() {
        this.loadData();
    }
    
    public render(){
        return (
            <FlatList
                data={this.state.listOfItems}
                renderItem={this.renderItem}
                onEndReachedThreshold={0.1}
                onEndReached={this.loadData}
            />
        );
    }
    
    private loadData = () => {
        if (this.state.isLoading === true) {
            /// Avoid make another request is there's happening a request right now
            return;
        }
    
        this.setState({isLoading: true});
    
        this.fetchData()
            .then(() => {
            /// Handle success response
                this.setState({isLoading: false});
            })
            .catch(() => {
                  this.setState({isLoading: false});
            });
    }
    

    }

    【讨论】:

    • 如何在不跳过第一次加载的情况下触发 isLoading 为“真”?
    • @user1230795 如果在您的 componentDidMount 方法中显式调用加载数据,这是最好的方法。 pd:我已经更新了我的回复,以使示例更加清晰。
    【解决方案5】:

    你可以试试我的解决方案

    1. 您应该配置限制 > 10。示例限制 = 15
    2. 将 onMomentumScrollBegin 属性添加到您的 ListView 声明中。

      <ListView
        data={this.props.data}
        onEndReached={...}
        onEndReachedThreshold={0.5}
        ...
        onMomentumScrollBegin={() => { this.onEndReachedCalledDuringMomentum = false; }}
      />
      
    3. 修改您的 onEndReached 回调以触发每个动量仅获取一次数据。

      onEndReached =()=> { if(!this.onEndReachedCalledDuringMomentum) { this.props.fetchData(); this.onEndReachedCalledDuringMomentum = true; } };

    【讨论】:

    【解决方案6】:

    您可以在onMomentumScrollEnd而不是onEndReached中编写获取数据的代码,如下所示:

    onMomentumScrollEnd={() => this.props.onEndReached()}
    

    它可能不会被写为 react native 文档中的可用 prop,但如果你会看到 FlatList 的源代码,它会使用 Virtualized List,而 Virtualized List 作为回报有提到的可用 prop。

    【讨论】:

      猜你喜欢
      • 2017-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-30
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      相关资源
      最近更新 更多