Giter VIP home page Giter VIP logo

m-list-view's Issues

pageSize设置稍大值时,快速滚动到底部会触发无限加载数据,即使数据已经足够渲染

感谢您将ListView组件移植到web平台。

遇到的问题:

在使用ListView组件的过程中发现当pageSize设置为稍大一点儿的值时,例如 10,快速滚动到页面底部会造成数据的不断加载,即使渲染的行数已经远远大于 onEndReachedThreshold 的值,仍然会不断触发onEndReached 请求数据;数据通过 props 接收;

问题分析:

经对ListVIew组件研究后发现,测量底部是否进入可见视图的动作只在 scroll 事件中完成,当快速滚动到底部时, getDistanceFromEnd(this.scrollProperties) < onEndReachedThreshold && curRenderedRowsCount === dataSource.getRowCount() 成立,会触发一次 onEndReached ,fetch新的数据后props接收,依次调用 render -> _maybeCallOnEndReached -> _renderMoreRowsIfNeeded -> _pageInNewRows -> render -> _maybeCallOnEndReached ... 因为没有scroll事件,所以getDistanceFromEnd(this.scrollProperties) < onEndReachedThreshold` 一直成立,从而陷入循环。

建议:

componentDidUpdate 中对底部是否进入可见视图进行判断并设置 scrollProperties,例如:

componentDidUpdate() {
    const isVertical = !this.props.horizontal;
    const target = ReactDOM.findDOMNode(this.refs[SCROLLVIEW_REF]);

    this.scrollProperties.visibleLength = target[
      isVertical ? 'offsetHeight' : 'offsetWidth'
      ];
    this.scrollProperties.contentLength = target[
      isVertical ? 'scrollHeight' : 'scrollWidth'
      ];
    this.scrollProperties.offset = target[
      isVertical ? 'scrollTop' : 'scrollLeft'
      ];
  }

throttle function does not work on my Android device

Hello,
The throttle function that is found on [project]/es/util.js does not seem to work on my Android device when making the listview scroll with a single fast touch gesture. The _onScroll handler is executed just once when the listview start scrolling (right after the touch gesture is performed) but then the listview start scrolling but no further _onScroll calls are registered.
For some reason the throttle function that is being used is NOT triggering calls every _this.props.scrollEventThrottle milliseconds.
On my desktop PC everything seems to be working well though.
I tried to replace the throttle function with this version I found here:
https://stackoverflow.com/a/27078401/3621841
... and this indeed works perfectly on both my desktop PC and my Android device.

So it seems this is a better function to use and I would like to ask you if you can make the change on the official version of the library if all your tests are passed.
Please let me know.
Thanks a lot!

关于行刷新的问题

image
当触发滚动加载了另外一屏,此时的_prevRenderedRowsCount不再是0,当触发更新的诱因不是滚动,比如选中某一行的选中态,对于每个已渲染的行此时shouldupdate永远是false,listview 就不会将父级的新属性传递给子集的行对象了,导致行对象里的组件无法获取父组件的状态

希望可以滚动到列表底部

我在做一个IM 聊天界面的时候,希望初始化和有消息更新的时候,列表的滚动条都可以滚动到底部。

scrollToCurrent() {
    const self = this
    setTimeout(() => {
      if (self.listView) {
        const { listviewRef } = self.listView
        if (listviewRef) {
          const scrollProperties = listviewRef.ListViewRef.getMetrics()
          if (scrollProperties) {
            const { contentLength, visibleLength } = scrollProperties
            if (contentLength && visibleLength) {
              const offset = contentLength - visibleLength
              if (offset > 0) {
                listviewRef.scrollTo(0, offset)
              }
            }
          }
        }
      }
    })
  }

使用以上的代码,拿到的 contentLength不是正确。

调整

  • refresh 不要附加到 ListView, 后期可能独立,使用 require('rmc-list-view/lib/RefreshControl');
  • RefreshControl prefixCls 为 rmc-refresh-control

代码整理

  • 统一使用 import export,去除 require,module.exports
  • 去除不必要依赖: react-mixin/autobind-decorator(use react.createClass),

在内部使用sticky时报错

需求是: 长列表只有一个吸顶,不是示例的那种很多标题吸顶,
所以我就改了一下,
把StickyContainer 放在了renderSectionBodyWrapper里面渲染
把Sticky 放在 renderHeader 里面渲染
复现:https://codesandbox.io/s/04xozqryjv
code:

export default class Demo extends React.Component {
...
return (
      <ListView
        ref={el => this.lv = el}
        dataSource={this.state.dataSource}
        className="am-list sticky-list"
        // useBodyScroll
        renderSectionBodyWrapper={() => (
          <StickyContainer
            // key={`s_${sectionID}_c`}
            className="sticky-container"
            style={{ zIndex: 4 }}
          />
        )}
        renderHeader={() => (
          <Sticky>
            {({
              style,
            }) => (
              <div
                className="sticky"
                style={{
                  ...style,
                  zIndex: 3,
                  backgroundColor: '#F8591A',
                  color: 'white',
                }}
              >{`Task 1`}</div>
            )}
          </Sticky>
        )}
...

然而结果却是 Uncaught TypeError: Expected Sticky to be mounted within StickyContainer,
该怎么解决呢?

Is this still being updated?

Last commit is over 1.5 years ago.
When using it now it will generate a lot of deprecation warnings when used.

Errors in throttle function after component is unmounted

Hello!
We are using this <ListView> component on some of our app screens.
When we enter screen A, the <ListView> component is mounted. All ok.
When we exit screen A, we unmount the whole screen, along with the <ListView> component.
The problem is that sometimes the throttle function used by <ListView> is still active (since it is an async function) and it calls its fn but now the <ListView> is already UNMOUNTED so an error like this is raised:

Uncaught TypeError: Cannot read property 'offsetHeight' of null
    at ScrollView.getMetrics (ScrollView.js?b514:228)
    at handleScroll (ScrollView.js?b514:83)
    at eval (util.js?c94d:32)

Basically the error chain is the following:

// util.js
export function throttle(fn, delay) {
  var delayFlag = true;
  var firstInvoke = true;
  // console.log('exec once');
  return function _throttle(e) {
    if (delayFlag) {
      delayFlag = false;
      setTimeout(function () {
        delayFlag = true;
        // console.log('exec delay time');
ERROR    fn(e);    --> ERROR HERE! (the throttled fn is called when the list component has been unmounted...)
// ScrollView.js    
    value: function componentDidMount() {
      var _this3 = this;

      var handleScroll = function handleScroll(e) {
ERROR    return _this3.props.onScroll && _this3.props.onScroll(e, _this3.getMetrics());  --> ERROR HERE!  (the onScroll function is called consequently, which involves a call to getMetrics)
// ScrollView.js
  this.getMetrics = function () {
    var isVertical = !_this5.props.horizontal;
    if (_this5.props.useBodyScroll) {
      // In chrome61 `document.body.scrollTop` is invalid,
      // and add new `document.scrollingElement`(chrome61, iOS support).
      // In old-android-browser and iOS `document.documentElement.scrollTop` is invalid.
      var scrollNode = document.scrollingElement ? document.scrollingElement : document.body;
      return {
        visibleLength: window[isVertical ? 'innerHeight' : 'innerWidth'],
        contentLength: _this5.ScrollViewRef[isVertical ? 'scrollHeight' : 'scrollWidth'],
        offset: scrollNode[isVertical ? 'scrollTop' : 'scrollLeft']
      };
    }
    return {
ERROR  visibleLength: _this5.ScrollViewRef[isVertical ? 'offsetHeight' : 'offsetWidth'],  --> ERROR HERE! (getMetrics fails since the component is unmounted!!!! and thus _this5.ScrollViewRef is NULL at this stage!!)

Basically the getMetrics function fails since the component is unmounted and thus _this5.ScrollViewRef is NULL at this stage.

Obviously the above error does not happen all the time but is VERY common.
My recommendation is that:

  1. Use a throttle function like https://github.com/lodash/lodash/tree/4.1.1-npm-packages/lodash.throttle (https://www.npmjs.com/package/lodash.throttle) which has a cancel method built in. So inside the componentWillUnmount you call this cancel method of the throttle function. To me this is the recommended solution.
  2. You add a condition inside the handleScroll function to check if the component is still mounted:
    key: 'componentDidMount',
    value: function componentDidMount() {
      var _this3 = this;
      _this3.mounted = true;

      var handleScroll = function handleScroll(e) {
        return _this3.mounted && _this3.props.onScroll && _this3.props.onScroll(e, _this3.getMetrics());
      };
      ...

See the _this3.mounted set and check. Obviously on the componentWillUnmount part you should set that property to false:

    key: 'componentWillUnmount',
    value: function componentWillUnmount() {
      if (this.props.useBodyScroll) {
        window.removeEventListener('scroll', this.handleScroll);
        window.removeEventListener('resize', this.onLayout);
      } else {
        this.ScrollViewRef.removeEventListener('scroll', this.handleScroll);
      }
      this.mounted = false;
    }
  1. Similarly we have to do something similar on 'componentDidUpdate':
    key: 'componentDidUpdate',
    value: function componentDidUpdate(prevProps) {
      var _this2 = this;

      // handle componentWillUpdate accordingly
      if ((this.props.dataSource !== prevProps.dataSource || this.props.initialListSize !== prevProps.initialListSize) && this.handleScroll) {
        setTimeout(function () {
          if (_this2.props.useBodyScroll) {
            window.addEventListener('scroll', _this2.handleScroll);
          } else {
            _this2.mounted && _this2.ScrollViewRef && _this2.ScrollViewRef.addEventListener('scroll', _this2.handleScroll);
          }
        }, 0);
      }
    }
      ...

... note the _this2.mounted condition

安卓4.4 列表不能滑动

runtime: webView android4.4 react16.4

判断一下应该是由于这个问题引起的:

<在Android下直接使用touchmove事件会在很多浏览器中出现每次操作只触发一次touchmove的情况。这是因为Android中对触屏事件奇葩解析造成的,在其它系统上没有这个情况。我们可以在touchstart事件中加入preventDefalut来解决,但这会带来其它问题。>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.