louis
louis

Reputation: 733

React Native Flatlist with pagination and pull to refresh

Hello good people on the internet. I am trying to implement a Flatlist with pull to refresh and pagination features however i am having issues especially with pull to refresh items. Here is my code

  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [hasnextpage, setHasNextPage] = useState(true);
  const [refresh, setRefresh] = useState(false);
  const { refreshing } = useContext(ExtrasContext);//called after an order has been processed so as to fetch latest products
 const products = useSelector((state) => state?.products?.products);//get products from redux 

fetch products from api

 const getAllproducts = async () => {
 console.log(page);//logging the current page here...
if (!loading && hasnextpage) { //hasnextpage set to true and is updated from api !loading ensures i dont call the function when the app is in loading state
  setLoading(true);
  try {
    const response = await axiosprivate.get(
      `bp_employee_get_all_products_information?page=${page}`,
      {
        headers: { Authorization: "Bearer " + auth?.accessToken },
      }
    );
    console.log(response);
    if (response?.data?.status === 200) {
      console.log(response?.data?.data);
      setHasNextPage(response?.data?.data?.hasNextPage); //returns true/false depending on data from the api
      const maxpage = response?.data?.data?.totalPages;//returns total pages in the api and guides me not to fetch more items if it reaches last page
      if ((page < maxpage )) {
        setPage((prev) => prev + 1);
        console.log("i was added");
      }
      dispatch(addProducts([...products, ...response?.data?.data.docs])); //add all products to redux state
      setLoading(false);
    } else {
      console.log("error found");
      setLoading(false);
    }
  } catch (error) {
    console.log(error);
    setLoading(false);
  }
} else return;

In clearproductlist down below i reset everything hence i set page to one but when i pull to refresh and when i log out the current page on the getAllProducts function it does not reset to 1.This is where I think the problem is I also reset setHasNextPage state to the original state,then clear the redux state that held the products

const clearproductlist = () => {
setPage(prev=>prev=1);//i tried setPage(1) didnt work. How do i reset this state?
setHasNextPage(true);
dispatch(clearProduct()); Clears everything in redux products state
};

As seen above i Reset everything

This function runs when i pull down to refresh

const Refresh = () => {
clearproductlist();
setRefresh(true);
getAllproducts();
setRefresh(false);
 };

The use effect below is called when an order/transaction happens, i do this to fetch new items as they are in the backend

useEffect(() => {
if (refreshing && refreshing) {
  Refresh();
  console.log("i run");
}
}, [refreshing]);

Below is my flatlist component

return (
<FlatList
      keyExtractor={keyExtractor}
      data={products}
      renderItem={renderItem}
      numColumns={viewchange === true ? 1 : 2}
      key={viewchange === true ? 1 : 2}
      onEndReachedThreshold={0.7}
      maxToRenderPerBatch={10}
      estimatedItemSize={50}
      onEndReached={getAllproducts}
      refreshing={refresh}
      onRefresh={Refresh}
      contentContainerStyle={{
        justifyContent: "space-between",
        paddingBottom: 100,
      }}
      ListFooterComponent={
        loading && (
          <View style={{ alignItems: "center" }}>
            <ActivityIndicator size="large" color="#0000ff" />
          </View>
        )
      }
      showsVerticalScrollIndicator={false}
    />
  )}
 )

Everything works fine except for pull to refresh. When I pull to refresh it does not reset the current page so it fetches what is is the page state i.e. 2 instead of 1 and hence loads items that I don't want. Any help will be appreciated

Upvotes: 0

Views: 2496

Answers (1)

Hari krishnani
Hari krishnani

Reputation: 11

This issue might be happening because storing value in state takes some time in react-native but you can try below solution,

On getAllproducts function you can pass page number as argument & then fetch page number from that args something like this..

const Refresh = () => {
 clearproductlist();
 setRefresh(true);
 getAllproducts(1);
 setRefresh(false);
};

And in getAllproducts you can fetch from argument like this..

 const getAllproducts = async (p = page) => {
 console.log(page);//logging the current page here...
if (!loading && hasnextpage) { //hasnextpage set to true and is updated from api !loading ensures i dont call the function when the app is in loading state
  setLoading(true);
  try {
    const response = await axiosprivate.get(
      `bp_employee_get_all_products_information?page=${p}`,
      {
        headers: { Authorization: "Bearer " + auth?.accessToken },
      }
    );

Upvotes: 1

Related Questions