3

我想在 ReactNative FlatList 中呈现项目列表,最初我加载 15 个项目,然后在用户向下滚动时加载更多项目。我正在使用 FlatList 的onEndReached道具来获取滚动的新项目。我正在使用一个带有 POST 方法的 api,该方法将一个包含 pageNumber、pageSize 等的对象作为输入并返回一个{ success: true, message: 'success.', data: [ items : [...] ] }包含列表项的对象。

为了实现这一点,我使用了 apisauce npm 包并编写了一个自定义钩子(useSearch.js)来处理形成 api 请求对象,然后调用 api 并获取项目。

当我向下滚动到屏幕时出现以下错误。当组件第一次加载时,我没有收到任何错误,但是当我滚动时,我遇到了错误。尝试了一段时间后,我意识到相同的代码适用于任何其他 Http GET 请求,但是当我使用 Http POST 方法时它不起作用。如何解决这个问题呢。任何帮助表示赞赏。

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s, a useEffect cleanup function, 
    in App (created by ExpoRoot)
    in RCTView (at NativeAppearance.tsx:4)
    in FallbackAppearanceProvider (at src/index.tsx:70)
    in AppearanceProvider (created by ExpoRoot)
    in RootErrorBoundary (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at AppContainer.js:109)
    in RCTView (at AppContainer.js:135)
    in AppContainer (at renderApplication.js:39)
TypeError: undefined is not an object (evaluating 'item.listingId.toString')

下面是我正在使用的代码

客户端.js

import { create } from "apisauce";

const apiClient = create({
  baseURL: 'http://localhost:9000',
});

export default apiClient;

useSearch.js(自定义挂钩)

const useSearch = () => {
  const searchList = { pageNumber: 1, pageSize: 15, sortField: "createddate", sortOrder: "desc", isActive: true};

  const [items, setItems] = useState([]);
  const [error, setError] = useState(false);
  const [pageNumber, setPageNumber] = useState(1);
  const [loading, setLoading] = useState(false);

  const endpoint = "/listings";

  const getItems = async (categoryId) => {
    setLoading(true);
    setPageNumber((prevPageNumber) => prevPageNumber + 1);

    const response = await apiClient.post(`${endpoint}/search`, {
      ...searchList,
      pageNumber,
      categoryId,
    });

    setLoading(false);
    if (!response.ok) {
      if (response.data && response.data.message) return setError(true);
      else return setError(true);
    }

    if (items && items.length > 0)
      setItems([...items, response.data?.data?.items]);
    else setItems(response.data?.data?.items);

    return response;
  };

  return {error, getItems, items, loading };
};

ListingsScreen.js(组件)

const ListingsScreen = ({ route }) => {
  const categoryId = route.params;

  const { items, getItems, loading } = useSearch();

  useEffect(() => {
    getItems(categoryId);
  }, []);

  return (
    <>
      <ActivityIndicator visible={loading} />
      <Screen style={styles.screen}>
        <FlatList
          showsVerticalScrollIndicator={false}
          data={items}
          keyExtractor={(item) => item.listingId.toString()}
          renderItem={({ item }) => (
            <CustomListItem onPress={() => console.log("On Press Item")} title={item.name} subTitle={item.category} />
          )}
          onEndReached={() => getItems(categoryId)}
          onEndReachedThreshold={0.5}
        />
      </Screen>
    </>
  );
};
4

0 回答 0