【问题标题】:React Native how to use FlatList inside nativebase Tabs onEndReach keep fire non-stopReact Native如何在nativebase Tabs onEndReach中使用FlatList保持火不停
【发布时间】:2018-03-26 11:35:41
【问题描述】:

我是 react native 的新手,所以我使用 3rd 方库中的一些组件并尝试尽可能使用 react native 组件。

反应原生:0.54 NativeBase:2.3.10 ....

我在 Nativebase 基于 scrollView 的 Tabs 内的 FlatList 有问题

  1. onEndReachedThreshold 无法正常工作,因为 Doc 说 0.5 将触发项目的横向滚动,但是当我设置 0.5 时,它不会触发最后一项的横向滚动,它会等到滚动到最后一项并触发 onEndReach。

  2. 如果我使用 ListFooterComponent 渲染加载时,我会遇到 onEndReach 问题,而数据未传递时它会不停地触发 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,
  }

加载类别

 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));
  }

在 Tabs 滑动或单击时检查 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 时加载更多产品

  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;
}

让我解释一下我的过程

  • 为活动的选项卡初始化 CategoryId 和 CategoIndex

  • 在 axios 触发后将获取所有类别并呈现选项卡项,因为 nativebase 选项卡错误,当 initailPage 大于 0 时它显示空白页,并且我使用 ref 触发它,当 this.tabIndex.goToPage 触发它调用时,类别完成加载onChange

  • onChage 事件开始检查在 StoreExistId 中是否存在 tabClick Ref,当他们单击时保存类别,如果为 true,我们将加载产品,否则我们什么也不做。我需要 ref,因为 React 状态是异步的,这使得我的产品第一次加载重复数据,所以 Ref 进来解决这个问题。

  • 当向下滚动到最后一项时,它将通过 API 上的分页加载MoreProduct

  • 我的数据状态如下 StoreExistId: [1,2,3,4] loadProduct: { 1: {data: [.....]}, 2: {data: [.....]}, etc.... }

提前致谢

【问题讨论】:

  • 你可能会遇到这个问题github.com/facebook/react-native/issues/6002
  • @akhilxavier 我看到有人提到设置固定高度,但我不知道应该在哪里设置它,因为我的项目是基于来自 Api 的项目渲染的。

标签: javascript reactjs react-native native-base


【解决方案1】:

一些 NativeBase 组件内部使用了 scrollView。我猜它可能是使用 ScrollView 的 ScrollableTab 组件?您不应该在 ScrollView 中使用 FlatList,这样 onReachEnd 将不起作用。

【讨论】:

  • 如果我不使用 Flatlist,我可以使用什么来获取 Scroll?例如 Twitter 应用程序,它在该选项卡下有选项卡和数据,并滚动到底部以加载更多数据。
  • 这方面有什么帮助吗?
【解决方案2】:

我遇到了同样的问题,解决方案是在 &lt;Content&gt; 内使用 &lt;FlatList&gt; 。欲了解更多信息,请参阅https://stackoverflow.com/a/54305517/8858217

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    相关资源
    最近更新 更多