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
RTK Query is a powerful data fetching and caching tool. It is designed to simplify common cases for loading data in a web application, eliminating the need to hand-write data fetching & caching logic yourself.
RTK Query can be added as a middleware and provides powerful React Hooks to help fetch your data. Despite its nascence, it's safe to say that when RTK Query goes into production, it will be a perfect candidate to fetch data in JavaScript apps of all sizes.
Now you can, by using Redux Toolkit and its latest addition: RTK Query. RTK Query is an advanced data-fetching and client-side caching tool. Its functionality is similar to React Query but it has the benefit of being directly integrated with Redux.
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:
Since we are lazy and do not want to track which direction we're scrolling to, just assume
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.
You can use queryFn
to assemble the cached results you already have. remember to use invalidation
to get the updated state.
In the following code, the first queryFn
is just a fake API, and the second endpoint is the solution you are looking for:
export const songsApi = createApi({
reducerPath: "songsApi",
baseQuery: fetchBaseQuery(),
endpoints: (builder) => ({
getSongs: builder.query<Result<Song>, { offset: number; limit: number }>({
queryFn: ({ offset, limit }) => {
let list: Song[] = [];
for (let i = offset; i < offset + limit; i++) {
list.push({ id: i.toString(), name: `Song ${i}` });
}
return new Promise((resolve) => {
setTimeout(() => {
resolve({
data: {
total: 100,
list
} as Result<Song>
});
}, 1000);
});
}
}),
getAllSongs: builder.query<Result<Song>, void>({
queryFn: (_, { getState }) => {
let state = getState();
let songs: Song[] = [];
for (let offset = 0; offset < 100; offset += 10) {
const { data } = songsApi.endpoints.getSongs.select({
offset,
limit: 10
})(state as any);
if (data && data.list) {
songs.push(...data!.list);
}
}
return Promise.resolve({ data: { total: 100, list: songs as Song[] } });
}
})
})
});
interface Result<T> {
total: number;
list: T[];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With