Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB]List在useBodyScroll时使用RefreshControll会无限触发onEndReached #1145

Closed
kimjuny opened this issue Apr 13, 2017 · 3 comments
Closed

Comments

@kimjuny
Copy link
Contributor

kimjuny commented Apr 13, 2017

ListViewuseBodyScroll时,如果同时配置了RefreshControl,只要开始上、下滑动(而不是到达onEndReachedThreshold的时候)就会无限触发onEndReached。多次尝试组合参数scrollRenderAheadDistance、scrollEventThrottle、onEndReachedThreshold结果都一样。

完整DEMO代码(其实就在官方DEMO上只添加了一行refreshControl={<RefreshControl onRefresh={() => {}} />}即可):

import React from 'react';
import { ListView, RefreshControl } from 'antd-mobile';

const data = [
  {
    img: 'https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png',
    title: '相约酒店',
    des: '不是所有的兼职汪都需要风吹日晒',
  },
  {
    img: 'https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png',
    title: '麦当劳邀您过周末',
    des: '不是所有的兼职汪都需要风吹日晒',
  },
  {
    img: 'https://zos.alipayobjects.com/rmsportal/hfVtzEhPzTUewPm.png',
    title: '食惠周',
    des: '不是所有的兼职汪都需要风吹日晒',
  },
];
let index = data.length - 1;

const NUM_ROWS = 20;
let pageIndex = 0;

class Test extends React.Component {
  constructor(props) {
    super(props);
    const dataSource = new ListView.DataSource({
      rowHasChanged: (row1, row2) => row1 !== row2,
    });

    this.genData = (pIndex = 0) => {
      const dataBlob = {};
      for (let i = 0; i < NUM_ROWS; i++) {
        const ii = (pIndex * NUM_ROWS) + i;
        dataBlob[`${ii}`] = `row - ${ii}`;
      }
      return dataBlob;
    };

    this.state = {
      dataSource: dataSource.cloneWithRows({}),
      isLoading: true,
    };
  }

  componentDidMount() {
    // you can scroll to the specified position
    // this.refs.lv.refs.listview.scrollTo(0, 200);

    // simulate initial Ajax
    setTimeout(() => {
      this.rData = this.genData();
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this.rData),
        isLoading: false,
      });
    }, 600);
  }

  // If you use redux, the data maybe at props, you need use `componentWillReceiveProps`
  // componentWillReceiveProps(nextProps) {
  //   if (nextProps.dataSource !== this.props.dataSource) {
  //     this.setState({
  //       dataSource: this.state.dataSource.cloneWithRows(nextProps.dataSource),
  //     });
  //   }
  // }

  onEndReached = (event) => {
    // load new data
    // hasMore: from backend data, indicates whether it is the last page, here is false
    if (this.state.isLoading && !this.state.hasMore) {
      return;
    }
    console.log('reach end', event);
    this.setState({ isLoading: true });
    setTimeout(() => {
      this.rData = { ...this.rData, ...this.genData(++pageIndex) };
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(this.rData),
        isLoading: false,
      });
    }, 1000);
  }

  render() {
    const separator = (sectionID, rowID) => (
      <div key={`${sectionID}-${rowID}`} style={{
        backgroundColor: '#F5F5F9',
        height: 8,
        borderTop: '1px solid #ECECED',
        borderBottom: '1px solid #ECECED',
      }}
      />
    );
    const row = (rowData, sectionID, rowID) => {
      if (index < 0) {
        index = data.length - 1;
      }
      const obj = data[index--];
      return (
        <div key={rowID} className="row">
          <div className="row-title">{obj.title}</div>
          <div style={{ display: '-webkit-box', display: 'flex', padding: '0.3rem 0' }}>
            <img style={{ height: '1.28rem', marginRight: '0.3rem' }} src={obj.img} />
            <div className="row-text">
              <div style={{ marginBottom: '0.16rem', fontWeight: 'bold' }}>{obj.des}</div>
              <div><span style={{ fontSize: '0.6rem', color: '#FF6E27' }}>{rowID}</span>元/任务</div>
            </div>
          </div>
        </div>
      );
    };

    return (
      <ListView ref="lv"
        dataSource={this.state.dataSource}
        renderHeader={() => <span>header</span>}
        renderFooter={() => <div style={{ padding: 30, textAlign: 'center' }}>
          {this.state.isLoading ? '加载中...' : '加载完毕'}
        </div>}
        renderRow={row}
        renderSeparator={separator}
        className="am-list"
        pageSize={4}
        scrollRenderAheadDistance={500}
        scrollEventThrottle={20}
        onScroll={() => { console.log('scroll'); }}
        useBodyScroll
        onEndReached={this.onEndReached}
        onEndReachedThreshold={10}
        refreshControl={<RefreshControl onRefresh={() => {}} />}
      />
    );
  }
}

export default Test;

@kimjuny
Copy link
Contributor Author

kimjuny commented Apr 13, 2017

现在是用ListView自定义容器配合RefreshControl,设置style(不用useBodyScroll)

style={{
  height: document.documentElement.clientHeight,
  overflow: 'auto',
}}

时才正常,只在到达底部时触发一次。�但是这种方式会在一些机型和浏览器发生蛋疼的问题。所以还是想问下要如何才能useBodyScroll + RefreshControl可以让onEndReached工作正常。

参考了下#520,部分的人所指的问题,应该是我遇到的这种情况。

@kimjuny kimjuny changed the title [WEB]List在useBodyScroll时使用RefreshControll会无线触发onEndReached [WEB]List在useBodyScroll时使用RefreshControll会无限触发onEndReached Apr 13, 2017
@warmhug
Copy link
Contributor

warmhug commented Apr 13, 2017

RefreshControl 需要 自定义容器 配合,参考


因为会开启 useZscroller ,这时 useBodyScroll 会失效掉,详细参考文档

@kimjuny
Copy link
Contributor Author

kimjuny commented Apr 13, 2017

@warmhug 好的,希望文档中可以有说明,否则可能会有很多人和我一样,以为这是个BUG。�

@ant-design ant-design locked and limited conversation to collaborators Sep 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants