Skip to content

Instantly share code, notes, and snippets.

@BenQoder
Last active April 25, 2023 14:57
Show Gist options
  • Select an option

  • Save BenQoder/ce1e9cd3fc882ccd7ad82276bf22ef36 to your computer and use it in GitHub Desktop.

Select an option

Save BenQoder/ce1e9cd3fc882ccd7ad82276bf22ef36 to your computer and use it in GitHub Desktop.
Implementing Infinite Scroll With Redux Toolkit Query
import { createApi } from "@reduxjs/toolkit/query/react";
import { createEntityAdapter } from "@reduxjs/toolkit";
// Create Adapter For Posts To Avoid Duplicates
const postsAdapter = createEntityAdapter({
selectId: (post) => post.id,
sortComparer: (a, b) => b.createdAt - a.createdAt,
});
const postsApi = createApi({
reducerPath: "posts",
endpoints: (build) => ({
fetchPosts: build.query({
keepUnusedDataFor: 600 // Keep unused for longer,
query: (page) => {
return `posts?page=${page}`;
},
transformResponse: (response) => {
// Return Post To State Using Adapters
return postsAdapter.addMany(
postsAdapter.getInitialState({
hasMorePages: response.hasMorePages,
}),
response.data
);
},
async onQueryStarted(page, { queryFulfilled, dispatch }) {
if (!page) {
return;
}
const { data } = await queryFulfilled;
if (data) {
// Add Posts On Current Request To Page 1
dispatch(
postsApi.util.updateQueryData(
"fetchPosts",
1,
(draft) => {
postsAdapter.addMany(
draft,
postsSelector.selectAll(data)
);
draft.hasMorePages;
}
)
);
if (page > 1) {
// Remove Cached Data From State Since We Already Added It To Page 1
dispatch(
postsApi.util.updateQueryData(
"fetchPosts",
page,
(draft) => {
draft = postsAdapter.getInitialState();
}
)
);
}
}
},
}),
}),
});
export const {
postsApi
} = postsApi;
export default postsApi;
const postsSelectors = postsAdapter.getSelectors((state) => state);
export { postsSelectors, postsAdapter };
import { View, FlatList } from "react-native";
import React, { useEffect, useRef } from "react";
import postsApi, {
postsAdapters,
postsSelectors,
useLazyFetchPostsQuery
} from "../../state/apis/postsApi";
export default function PostsScreen() {
const currentPage = useRef(1);
const [fetchPosts, { isFetching }] =
useLazyFetchPostsQuery();
// Listen For Posts Updates Page 1
const { posts, hasMorePages } =
postsApi.endpoints.fetchPosts.useQueryState(1, {
selectFromResult: (result) => {
return {
hasMorePages: result.data?.hasMorePages,
posts: postsSelectors.selectAll(
result.data ?? postsAdapters.getInitialState()
),
};
},
});
const fetchFirstPage = async () => {
await fetchPosts(currentPage.current);
};
const fetchMorePosts = async () => {
if(!hasMorePages || isFetching) return;
currentPage.current += 1;
await fetchPosts(currentPage.current);
};
useEffect(() => {
// Fetch First Page On Init
fetchFirstPage()
},{})
return (
<FlatList
data={posts}
renderItem={....}
onEndReached={fetchMorePosts}
/>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment