@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
135 lines • 5.07 kB
JavaScript
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useLazyFetchCollectionEntitiesQuery } from "../../store/api/collectionsApi";
import { handleError } from "../../utils/handleError";
import useProject from "../projects/useProject";
import useCollections from "./useCollections";
import { useReplykeDispatch, useReplykeSelector } from "../../store/hooks";
import { setCollectionEntities, appendCollectionEntities, selectCollectionEntities, } from "../../store/slices/collectionsSlice";
function useCollectionEntitiesWrapper(props) {
const { collectionId: passedCollectionId, limit = 20, defaultSortBy = "added", defaultSortDir = "desc", include, } = props;
const dispatch = useReplykeDispatch();
const { projectId } = useProject();
const { currentCollection } = useCollections();
const [fetchCollectionEntitiesQuery] = useLazyFetchCollectionEntitiesQuery();
const effectiveCollectionId = passedCollectionId ?? currentCollection?.id;
// Read entities from shared Redux state — written here and by useCollectionsActions for optimistic updates
const entities = useReplykeSelector(selectCollectionEntities(effectiveCollectionId));
const includeString = useMemo(() => (Array.isArray(include) ? include.join(",") : include), [include]);
const loading = useRef(false);
const [loadingState, setLoadingState] = useState(false);
const hasMore = useRef(true);
const [hasMoreState, setHasMoreState] = useState(true);
const [sortBy, setSortBy] = useState(defaultSortBy);
const [sortDir, setSortDir] = useState(defaultSortDir);
const [page, setPage] = useState(1);
const resetEntities = useCallback(async () => {
if (!projectId || !effectiveCollectionId) {
return;
}
try {
loading.current = true;
setLoadingState(true);
hasMore.current = true;
setHasMoreState(true);
setPage(1);
const response = await fetchCollectionEntitiesQuery({
projectId,
collectionId: effectiveCollectionId,
page: 1,
limit,
sortBy,
sortDir,
include,
}).unwrap();
if (response) {
const { data: newEntities, pagination } = response;
dispatch(setCollectionEntities({ collectionId: effectiveCollectionId, entities: newEntities }));
hasMore.current = pagination.hasMore;
setHasMoreState(pagination.hasMore);
}
}
catch (err) {
handleError(err, "Failed to fetch collection entities:");
}
finally {
loading.current = false;
setLoadingState(false);
}
}, [
dispatch,
fetchCollectionEntitiesQuery,
projectId,
effectiveCollectionId,
limit,
sortBy,
sortDir,
includeString,
]);
const loadMore = useCallback(() => {
if (loading.current || !hasMore.current)
return;
setPage((prevPage) => prevPage + 1);
}, []);
useEffect(() => {
resetEntities();
}, [resetEntities]);
useEffect(() => {
const loadMoreEntities = async () => {
if (!projectId || !effectiveCollectionId) {
return;
}
loading.current = true;
setLoadingState(true);
try {
const response = await fetchCollectionEntitiesQuery({
projectId,
collectionId: effectiveCollectionId,
page,
limit,
sortBy,
sortDir,
include,
}).unwrap();
if (response) {
const { data: newEntities, pagination } = response;
dispatch(appendCollectionEntities({ collectionId: effectiveCollectionId, entities: newEntities }));
hasMore.current = pagination.hasMore;
setHasMoreState(pagination.hasMore);
}
}
catch (err) {
handleError(err, "Loading more collection entities failed:");
}
finally {
loading.current = false;
setLoadingState(false);
}
};
if (page > 1 && hasMore.current && !loading.current) {
loadMoreEntities();
}
}, [
page,
dispatch,
fetchCollectionEntitiesQuery,
projectId,
effectiveCollectionId,
limit,
sortBy,
sortDir,
includeString,
]);
return {
entities,
loading: loadingState,
hasMore: hasMoreState,
sortBy,
sortDir,
setSortBy,
setSortDir,
loadMore,
refetch: resetEntities,
};
}
export default useCollectionEntitiesWrapper;
//# sourceMappingURL=useCollectionEntitiesWrapper.js.map