React Native如何在nativebase中使用FlatList Tabs onEndReach保持不停火

问题描述 投票:0回答:2

我是新的反应原生,所以我使用第三方库中的一些组件,并尝试尽可能使用反应原生组件。

ReactNative:0.54 NativeBase:2.3.10 ....

我在基于scrollView的Nativebase中的Tabs内遇到问题

  1. onEndReachedThreshold无法正常工作,因为Doc说0.5将触发haft方式滚动项目但是当我设置0.5时它不会触发到最后一项的方式它等到滚动到最后一项并触发onEndReach。
  2. 我有onEndReach的问题,如果我使用ListFooterComponent渲染加载数据不传递时它会不停地触发onEndReach。

这是我的代码

检查道具和初始状态

  static getDerivedStateFromProps(nextProps) {
    const { params } = nextProps.navigation.state;
    const getCategoryId = params ? params.categoryId : 7;
    const getCategoryIndex = params ? params.categoryIndex : 0;
    return {
      categoryId: getCategoryId,
      categoryIndex: getCategoryIndex,
    };
  }
  state = {
    loadCategoryTab: { data: [] },
    loadProduct: {},
    storeExistId: [],
    loading: false,
    refreshing: false,
  }

loadCategory

 componentDidMount() { this.onLoadCategory(); }
  onLoadCategory = () => {
    axios.get(CATEGORY_API)
      .then((res) => {
        this.setState({ loadCategoryTab: res.data }, () => {
          setTimeout(() => { this.tabIndex.goToPage(this.state.categoryIndex); });
        });
      }).catch(error => console.log(error));
  }

选项卡滑动或单击时检查onChange事件

  onScrollChange = () => {
    const targetId = this.tabClick.props.id;
    this.setState({ categoryId: targetId });
    if (this.state.storeExistId.indexOf(targetId) === -1) {
      this.loadProductItem(targetId);
    }
  }
  loadProductItem = (id) => {
    axios.get(`${PRODUCT_API}/${id}`)
      .then((res) => {
        /*
        const {
          current_page,
          last_page,
          next_page_url,
        } = res.data;
        */
        this.setState({
          loadProduct: { ...this.state.loadProduct, [id]: res.data },
          storeExistId: this.state.storeExistId.concat(id),
        });
      })
      .catch(error => console.log(error));
  }

当onEndReach被触发时,loadMoreProduct

  loadMoreProductItem = () => {
    const { categoryId } = this.state;
    const product = has.call(this.state.loadProduct, categoryId)
      && this.state.loadProduct[categoryId];
    if (product.current_page !== product.last_page) {
      axios.get(product.next_page_url)
        .then((res) => {
          const {
            data,
            current_page,
            last_page,
            next_page_url,
          } = res.data;
          const loadProduct = { ...this.state.loadProduct };
          loadProduct[categoryId].data = product.data.concat(data);
          loadProduct[categoryId].current_page = current_page;
          loadProduct[categoryId].last_page = last_page;
          loadProduct[categoryId].next_page_url = next_page_url;
          this.setState({ loadProduct, loading: !this.state.loading });
        }).catch(error => console.log(error));
    } else {
      this.setState({ loading: !this.state.loading });
    }
  }

渲染()

      render() {
        const { loadCategoryTab, loadProduct } = this.state;
        const { navigation } = this.props;
        return (
          <Container>
            <Tabs
              // NB 2.3.10 not fix yet need to use `ref` to replace `initialPage`
              ref={(component) => { this.tabIndex = component; }}
              // initialPage={categoryIndex}
              renderTabBar={() => <ScrollableTab tabsContainerStyle={styles.tabBackground} />}
              onChangeTab={this.onScrollChange}
              // tabBarUnderlineStyle={{ borderBottomWidth: 2 }}
            >
              {
                loadCategoryTab.data.length > 0 &&
                loadCategoryTab.data.map((parentItem) => {
                  const { id, name } = parentItem;
                  const dataItem = has.call(loadProduct, id) ? loadProduct[id].data : [];
                  return (
                    <Tab
                      key={id}
                      id={id}
                      ref={(tabClick) => { this.tabClick = tabClick; }}
                      heading={name}
                      tabStyle={styles.tabBackground}
                      activeTabStyle={styles.tabBackground}
                      textStyle={{ color: '#e1e4e8' }}
                      activeTextStyle={{ color: '#fff' }}
                    >
                      <FlatList
                        data={dataItem}
                        keyExtractor={subItem => String(subItem.prod_id)}
                        ListEmptyComponent={this.onFirstLoad}
                        // ListFooterComponent={this.onFooterLoad}
                        refreshing={this.state.refreshing}
                        onRefresh={this.handleRefresh}
                        onEndReachedThreshold={0.5}
                        onEndReached={() => {
                            this.setState({ loading: !this.state.loading }, this.loadMoreProductItem);
                        }}
                        renderItem={({ item }) => {
                          const productItems = {
                            item,
                            navigation,
                          };
                          return (
                            <ProductItems {...productItems} />
                          );
                        }}
                      />
// this OnLoadFooter is my tempory show loading without ListFooterComponent but i don't want to show loading outside FlatList hope i will get a help soon
                      <OnLoadFooter loading={this.state.loading} style={{ backgroundColor: '#fff' }} />
                    </Tab>
                  );
                })
              }
            </Tabs>
          </Container>
        );
      }

加载组件

function OnLoadFooter(props) {
  if (props.loading) return <Spinner style={{ height: 50, paddingVertical: 10 }} />;
  return null;
}

让我解释一下我的过程

  • init的CategoryId和CategoIndex for Tabs处于活动状态
  • axios fire之后将获取所有类别并呈现Tab项,因为nativeexe Tabs bug当initailPage大于0时显示空白页面并且我使用ref触发它当类别完成加载时this.tabIndex.goToPage触发它调用onChange
  • onChage事件开始检查StoreExistId中是否存在tabClick Ref,当他们点击时保存类别如果为true我们加载产品,否则我们什么都不做。我需要参考,因为React状态是异步使我的产品第一次加载重复数据,所以Ref来解决这个问题。
  • 当向下滚动到最后一项时,它将通过API上的分页加载更多产品
  • 我的数据状态如下 StoreExistId: [1,2,3,4] loadProduct: { 1: {data: [.....]}, 2: {data: [.....]}, etc.... }

谢谢高级

javascript reactjs react-native native-base
2个回答
1
投票

一些NativeBase组件使用scrollView。我想它可能是使用ScrollView的ScrollableTab组件?你不应该在ScrollView中使用FlatList,onReachEnd将不起作用。


0
投票

我面临同样的问题,解决方案是在<FlatList>内使用<Content>。有关更多信息,请参阅https://stackoverflow.com/a/54305517/8858217

© www.soinside.com 2019 - 2024. All rights reserved.