Search code examples
reactjsreduxredux-toolkitrtk-query

Is there any way to fetch all the responses stored in api slice [RTK Query]?


Here's the hook which returns the data based on the page

    const {
        data,
        isFetching,
        isLoading,
        isError,
    } = useGetResourceQuery(page, perPage );

here's the api

    export const api = createApi({
        baseQuery: fetchBaseQuery({
            baseUrl: "http://localhost:3001",
        
        }),
        tagTypes: ["resource"],
        endpoints: (build) => ({
            getResource: build.query({
            query: (page = 1, perPage = 20) =>
                `resource?spage=${page}&limit=${perPage}`,
            }),
        }),
    });
    export const {useGetResourceQuery} = api

Is there any way we can extract the state of all the queries? I want to implement pagination based on scroll (infinite scroll) Do we need to update the middleware? or are there any ways to access the state and expose it as a function above, I went through the documentation but couldn't find a solution

I can use local state and concatenate them but wanted to know if it's possible using RTK

Thanks


Solution

  • I think most implementations overcomplicate the problem of "infinite scroll" by a lot. You can achieve this by stepping a bit back and thinking about what you really need:

    • the current in-view data
    • a bit extra data into the direction we're scrolling to

    Since we are lazy and do not want to track which direction we're scrolling to, just assume

    • the current in-view data
    • a bit extra data into both directions.

    Also let's assume the query returns a response like

      {
        offset: 50,
        items: [...]
      }
    

    So assuming one page is big enough to contain all the data for a screen, we'd end up with something like

    const currentPage = // something calculated from ScrollPosition
    
    const lastResult = usePageQuery(currentPage - 1, { skip: currentPage === 1 }) // don't fetch pages before 0
    const currentResult = usePageQuery(currentPage)
    const nextResult = usePageQuery(currentPage + 1)
    
    const combined = useMemo(() => {
      const arr = new Array(pageSize * (currentPage + 1))
      for (const data of [lastResult.data, currentResult.data, nextResult.data]) {
        if (data) {
          arr.splice(data.offset, data.items.length, ...data.items)
        }
      }
      return arr
    }, [pageSize, currentPage, lastResult.data, currentResult.data, nextResult.data])
    
    // work with `combined` here
    

    Since requests that are not referenced by your component, will stay in the store for 60 seconds, the user can scroll up quickly through many pages without further requests - but also, data that will probably never scrolled to again will be removed from the cache and simply re-fetched when necessary.