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 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.
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>
</>
);
};
How to solve this problem.? Any help is appreciated.