|
1 | 1 | import { useState, useEffect, useCallback } from "react" |
2 | 2 | import { useFetcher, useSearchParams, href } from "react-router" |
| 3 | +// 💰 use this to type the route |
3 | 4 | import { type Route } from "./+types/route" |
4 | 5 |
|
5 | 6 | export function useInfiniteProductFetcher( |
6 | | - loaderData: Route.ComponentProps['loaderData'], |
| 7 | + // 🐨 we want to type the loader data to be the type of the returned loader data of the products listing page |
| 8 | + // 💰 Route.ComponentProps['loaderData'] |
| 9 | + loaderData: any, |
7 | 10 | ) { |
8 | | - const fetcher = useFetcher<Route.ComponentProps['loaderData']>({ |
| 11 | + // 💰 we are fetching from the same loader, so we can type this fetcher with the same type as loader-data |
| 12 | + const fetcher = useFetcher<any>({ |
9 | 13 | key: 'infinite-product-fetcher', |
10 | 14 | }) |
| 15 | + // 💰 we are extracting the initial data we fetched and then we will load more from the server |
11 | 16 | const { products, pagination } = loaderData |
12 | 17 | const [allProducts, setAllProducts] = useState(products) |
13 | 18 | const [currentPage, setCurrentPage] = useState(pagination.page) |
14 | 19 | const [hasMore, setHasMore] = useState(pagination.hasMore) |
15 | 20 | const [isLoadingMore, setIsLoadingMore] = useState(false) |
16 | 21 | const [searchParams] = useSearchParams() |
17 | 22 | useEffect( |
| 23 | + // 🐨 whenever we change the filters we should start from the beginning again |
18 | 24 | function resetStateOnLoaderRefire() { |
19 | | - //setAllProducts(products) |
20 | | - // setCurrentPage(pagination.page) |
21 | | - // setHasMore(pagination.hasMore) |
| 25 | + // 💰 whenever we reset the URL and the loader returns new products, we want to reset the state to the initial values |
| 26 | + // 💰 setAllProducts(products) |
| 27 | + // 💰 setCurrentPage(pagination.page) |
| 28 | + // 💰 setHasMore(pagination.hasMore) |
| 29 | + |
22 | 30 | }, |
23 | 31 | [pagination.hasMore, pagination.page, products], |
24 | 32 | ) |
25 | 33 |
|
26 | 34 | useEffect( |
| 35 | + |
| 36 | + // 🐨 whenever we load the new products we want to append them to the existing array |
27 | 37 | function setNewlyLoadedProducts() { |
28 | | - if (fetcher.data && fetcher.state === 'idle' && isLoadingMore) { |
29 | | - //setAllProducts((prev) => [...prev, ...(fetcher.data?.products ?? [])]) |
30 | | - // setCurrentPage(fetcher.data.pagination.page) |
31 | | - //setHasMore(fetcher.data.pagination.hasMore) |
32 | | - // setIsLoadingMore(false) |
| 38 | + // 💰 we want to make sure that the fetcher has returned some data and it's defined, and it is idle and we were loading more products |
| 39 | + if (false) { |
| 40 | + // 💰 we append the newly loaded products to the existing array |
| 41 | + // 💰 setAllProducts((prev) => [...prev, ...(fetcher.data.? ??[])]) |
| 42 | + // 💰 we update the current page |
| 43 | + // 💰 setCurrentPage(fetcher.data.?) |
| 44 | + // 💰 we update the hasMore flag |
| 45 | + // 💰 setHasMore(fetcher.data.?) |
| 46 | + // 💰 we set isLoadingMore to false |
| 47 | + // 💰 setIsLoadingMore(false) |
33 | 48 | } |
34 | 49 | }, |
35 | 50 | [fetcher.data, fetcher.state, isLoadingMore], |
36 | 51 | ) |
37 | 52 |
|
38 | 53 | const loadMoreProducts = useCallback(() => { |
39 | | - // setIsLoadingMore(true) |
40 | | - // const nextPage = currentPage + 1 |
| 54 | + // 🐨 we want to create the new search params so we can submit that to the loader so it gives us the next page of results |
| 55 | + // 💰 we set the flag to true |
| 56 | + // 💰 setIsLoadingMore(true) |
| 57 | + // 💰 we use the current page to create the next page |
| 58 | + // 💰 const nextPage = currentPage + 1 |
| 59 | + |
| 60 | + // 💰 Create URL params for the fetch |
| 61 | + // 💰 const params = new URLSearchParams(searchParams) |
| 62 | + // 💰 params.set('page', nextPage.toString()) |
41 | 63 |
|
42 | | - // Create URL params for the fetch |
43 | | - // const params = new URLSearchParams(searchParams) |
44 | | - // params.set('page', nextPage.toString()) |
| 64 | + // 🐨 finally we want to load the next page using the fetcher |
| 65 | + // 💰 use the `load` function and call the /products page in a type-safe manner (href function) and append the search params |
| 66 | + // 💰 + "?" + params.toString() |
45 | 67 |
|
46 | | - // void fetcher.load(href('/products') + '?' + params.toString()) |
47 | 68 | }, [currentPage, fetcher, searchParams]) |
48 | 69 |
|
49 | 70 | return { fetcher, loadMoreProducts, allProducts, hasMore, isLoadingMore } |
|
0 commit comments