首页 > 解决方案 > React Native 应用程序在获取 API 时冻结

问题描述

嗨,我有一个非常常见的问题,在获取 API 时反应本机应用程序冻结,就像当你获取时你不能点击或做任何事情,直到你的获取结束。

这是我调用获取 APi 的函数的代码

import React, { useEffect, useState } from "react";
import { StyleSheet, View, FlatList } from "react-native";

// Api`s
import { topCategory } from "../../api/appModels/category";
import { banners } from "../../api/appModels/slider";
import { dinamicBlocks } from "../../api/appModels/product";

// Hooks
import useApi from "../../Hooks/useApi";

// UI-Components
import Container from "../../uicomponents/General/Container";
import BannerSlider from "../../uicomponents/Slider/BannerSlider";
import Screen from "../../uicomponents/General/Screen";
import TopProductPattern from "../../uicomponents/Category/pattern/TopProductPattern";
import SliderPlaceholder from "../../uicomponents/Skeleton/Sliders/SliderPlaceholder";
import CategoryAvatarPlaceholder from "../../uicomponents/Skeleton/Category/CategoryAvatarPlaceholder";
import CategoryBlocks from "../../uicomponents/Product/blocks/CategoryBlocks";
import Header from "../../uicomponents/header/Header";
import ActivityIndicator from "../../uicomponents/Loaders/ActivityIndicator";

const HomeScreen = () => {
  const {
    data: topCategoryList,
    loading: topCategoryLoading,
    request: categoryRequest,
  } = useApi(topCategory);

  const {
    data: bannersList,
    loading: bannerLoading,
    request: bannersRequest,
  } = useApi(banners);

  const {
    loading: blocksLoading,
    request: blocksRequest,
  } = useApi(dinamicBlocks);

  const [blocks, setBlocks] = useState([]);
  const [indexing, setIndexing] = useState(1);
  const [countBlocks, setCountBlocks] = useState(0);
  const [loader, setLoader] = useState(false);

  useEffect(() => {
    // Calling Api`s
    categoryRequest();
    bannersRequest();
    blocksRequest((item) => {
      setIndexing(indexing + 1);
      setBlocks(item["blocks"]);
      setCountBlocks(item["count"]);
    }, 1);
  }, []);

  const loadMore = () => {
    if (!blocksLoading) {
      blocksRequest((item) => {
        setIndexing(indexing + 1);
        setBlocks(blocks.concat(item["blocks"]));
        console.log(item);
      }, indexing);
      setLoader(indexing != countBlocks);
    }
  };

  return (
    <Screen>
      <FlatList
        data={blocks}
        keyExtractor={(item) => item.categories.toString()}
        ListHeaderComponent={
          <>
            <Header />
            {bannerLoading ? (
              <SliderPlaceholder />
            ) : (
              <BannerSlider data={bannersList} dots />
            )}
            <Container>
              <View style={{ paddingTop: 10 }}>
                {topCategoryLoading ? (
                  <CategoryAvatarPlaceholder />
                ) : (
                  <TopProductPattern data={topCategoryList} />
                )}
              </View>
            </Container>
          </>
        }
        ListFooterComponent={<ActivityIndicator visible={loader} />}
        renderItem={({ item }) => (
          <CategoryBlocks title={item.blocks_name} data={item.categoriesList} />
        )}
        onEndReached={loadMore}
        onEndReachedThreshold={0.1}
      />
    </Screen>
  );
};

export default HomeScreen;

const styles = StyleSheet.create({});

这是我获取 API 的代码

import { useState } from "react";

const useApi = (apiFunc) => {
  const [data, setData] = useState([]);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);

  const request = async (callBack = () => {}, ...args) => {
    setLoading(true);
    const response = await apiFunc(...args);

    if (!response.ok) return setError(response.problem);

    setLoading(false);

    setError("");
    setData(response.data);
    if (response.ok) {
      callBack(response.data);
    }
  };

  return {
    data,
    error,
    loading,
    request,
    setLoading,
    setData,
  };
};

export default useApi;

我认为 RN-bridge 有问题 请帮助我!

标签: javascriptreactjsreact-nativefreeze

解决方案


可能发生这种情况是因为您设置了 onEndReachedThreshold={0.1}并且当加载数据时,将再发送一次请求并且它会出现问题。

因此,您可以将此值增加到例如0.7

在react Native官方网站上对EndReachedThreshold是这样解释的:

"列表的底部边缘必须距离内容的末尾多远(以列表的可见长度为单位)才能触发 onEndReached 回调。因此,值为 0.5 将在内容结束时触发 onEndReached在列表可见长度的一半以内。”


推荐阅读