3

I want to render a list of items in a ReactNative FlatList, initially I am loading 15 items and then load more when user scrolls down. I am using FlatList's onEndReached prop to get new items on scroll. I am consuming an api with POST method, which takes an object containing pageNumber, pageSize etc., as input and returns an object { success: true, message: 'success.', data: [ items : [...] ] } containing list items.

To achieve this I am using apisauce npm package and written a custom hook(useSearch.js) which handles forming api request object and then invoke api and get items.

I am getting below error when I scroll down to the screen. When the component loads first time I am not getting any error but when I scroll I am getting below error. After trying some time I realized that same code is working for any other Http GET requests, but when I use Http POST method its not working. How to solve this problem. Any help is appreciated.

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')

Below is the code I am using

client.js

import { create } from "apisauce";

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

export default apiClient;

useSearch.js (Custom Hook)

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 (Component)

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

0 Answers0