componentDidMount method of HOC causes Excessive number of pending callbacks: 501

33 Views Asked by At

I have a lazy loading HOC that wraps a component with a ScrollView. The HOC accepts a data array that is sliced and incrementally passed to the wrapped component when it scrolls to the bottom of the viewport. The HOC also executes a callback function on the original data in its componentDidMount method.

HOC Component

const withLazyLoading = WrappedComponent => {
  return class extends React.Component {
    static propTypes = {
      data: PropTypes.array,
      start: PropTypes.number,
      limit: PropTypes.number,
      bottomOffset: PropTypes.number,
      dataKey: PropTypes.string,
      onScrollBottom: PropTypes.func,
      omMount: PropTypes.func,
    };

    static defaultProps = {
      data: [],
      dataKey: 'photos',
      start: 0,
      limit: 20,
      bottomOffset: 20,
      onScrollBottom: _.noop,
      onMount: _.noop,
    };

    constructor(props) {
      super(props);
      this.state = {
        offset: _end(props.data, props.start + props.limit),
        loaded: props.data.slice(props.start, props.start + props.limit),
        total: props.data.length,
        loading: false,
      };
    }

    componentDidMount() {
      const { data } = this.props;
      this.props.onMount(data);
    }

    ...

    onScrollBottom(e) {
      const {
          nativeEvent: { layoutMeasurement, contentOffset, contentSize },
        } = e,
        { onScrollBottom: callback, bottomOffset } = this.props;

      if (
        layoutMeasurement.height + contentOffset.y >=
        contentSize.height - bottomOffset
      ) {
        this.load();
        if (callback && _.isFunction(callback)) {
          e.persist();
          callback(e);
        }
      }
    }

    ...

    render() {
      const { dataKey, data } = this.props,
        { loaded, loading } = this.state,
        childProps = {
          ..._.omit(this.props, ['data']),
          onScrollBottom: this.onScrollBottom.bind(this),
          [dataKey]: loaded,
          original: data,
        };
      return (
        <>
          {loading && this.renderLoadingView()}
          <WrappedComponent {...childProps} />
        </>
      );
    }
  };
};

export default withLazyLoading;

Wrapped Component

const deviceHeight = Dimensions.get('window').height;
const scrollLimit = deviceHeight ? deviceHeight / 3 : 20;

const prefetchPhotos = data => {
  const uris = data.reduce((u, i) => {
    if (i.preview_photo) {
      u.push(i.preview_photo);
    }
    return u;
  }, []);
  CacheManager.prefetch(uris);
};

class ItemsPage extends Component {

  ...

  renderItemsGrid() {
    const { items } = this.props,
      { dragging } = this.state;
    return (
      <Content
        scrollEnabled={!dragging}
        extraScrollHeight={70}
        style={[styles.bottomPadderSm]}
        stickyHeaderIndices={[0]}
        onMomentumScrollEnd={this.props.onScrollBottom}>
        ...
        <SwipeListView
          data={items}
          ref={e => (this._swipeListView = e)}
          renderItem={this.renderItem}
          renderHiddenItem={this.renderHiddenItem}
          leftOpenValue={110}
          leftActivationValue={110}
          swipeToOpenPercent={15}
          swipeToClosePercent={25}
          previewRowKey={
            (items || []).length > 1 ? `${_.first(items || [])?.id || 0}` : null
          }
          previewOpenValue={40}
          previewOpenDelay={1500}
          onRowDidOpen={this.onRowDidOpen}
          swipeGestureBegan={this.swipeGestureBegan}
          swipeGestureEnded={this.swipeGestureEnded}
          onLeftActionStatusChange={this.onRowWillOpen}
          disableLeftSwipe={true}
          closeOnRowPress={true}
          closeOnRowOpen={true}
          keyExtractor={(item, i) => `${item.id}`}
        />
      </Content>
    );
  }
  ...
  render() {
    ...
    {items.length === 0 ? this.renderEmtpyView() : this.renderItemsGrid()}
    ...
  }
}

export default connect(
  state => ({
    ...
    data: state.sales.activeSale ? state.sales.activeSale.items || [] : [],
    dataKey: 'items',
    limit: 20,
    bottomOffset: scrollLimit,
    onMount: prefetchPhotos,
  }),
  { ... },
)(withLazyLoading(ItemsPage));

I get the following error on an initial navigation to the ItemsPage screen.

Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"121":{"module":"NativeAnimatedModule","method":"startAnimatingNode"},"4863":{"module":"UIManager","method":"measure"},"4875":{"module":"NativeAnimatedModule","method":"startAnimatingNode"},"6012":{},

But when I remove componentDidMount method of WithLazyLoading, the error goes away. Any ideas on why I am getting the error or what is causing it? Based on other reports, the error may be promise related, but I am unsure where and how this is occurring.

0

There are 0 best solutions below