@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
135 lines • 5.54 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const useFetchManyComments_1 = __importDefault(require("./useFetchManyComments"));
const handleError_1 = require("../../utils/handleError");
const addCommentsToTree_1 = require("../../helpers/addCommentsToTree");
const removeCommentFromTree_1 = require("../../helpers/removeCommentFromTree");
const markCommentAsDeletedInTree_1 = require("../../helpers/markCommentAsDeletedInTree");
function useEntityComments(props) {
const { entityId, limit = 10, defaultSortBy = "new", include } = props;
const fetchManyComments = (0, useFetchManyComments_1.default)();
const loading = (0, react_1.useRef)(true);
const [loadingState, setLoadingState] = (0, react_1.useState)(true); // required to trigger rerenders
const hasMore = (0, react_1.useRef)(true);
const [hasMoreState, setHasMoreState] = (0, react_1.useState)(true); // required to trigger rerenders
const [sortBy, setSortBy] = (0, react_1.useState)(defaultSortBy);
const [page, setPage] = (0, react_1.useState)(1);
const [entityCommentsTree, setEntityCommentsTree] = (0, react_1.useState)({});
const { comments, newComments } = (0, react_1.useMemo)(() => {
const allRootComments = Object.values(entityCommentsTree).filter((item) => !item.comment.parentId);
const comments = allRootComments
.filter((entry) => !entry.new)
.map((entry) => entry.comment);
const newComments = allRootComments
.filter((entry) => !!entry.new)
.map((entry) => entry.comment)
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
return { comments, newComments };
}, [entityCommentsTree]);
const addCommentsToTree = (newComments, newlyAdded) => {
(0, addCommentsToTree_1.addCommentsToTree)(setEntityCommentsTree, newComments, newlyAdded);
};
const removeCommentFromTree = (0, react_1.useCallback)(({ commentId }) => {
setEntityCommentsTree((prevTree) => (0, removeCommentFromTree_1.removeCommentFromTree)(prevTree, commentId));
}, [setEntityCommentsTree]);
const markCommentAsDeleted = (0, react_1.useCallback)(({ commentId }) => {
setEntityCommentsTree((prevTree) => (0, markCommentAsDeletedInTree_1.markCommentAsDeletedInTree)(prevTree, commentId));
}, [setEntityCommentsTree]);
const resetComments = (0, react_1.useCallback)(async () => {
if (!entityId) {
return;
}
try {
loading.current = true;
setLoadingState(true);
hasMore.current = true;
setHasMoreState(true);
setEntityCommentsTree({});
setPage(1);
const response = await fetchManyComments({
entityId,
page: 1,
sortBy,
limit,
include,
});
if (response) {
const { data: newComments, pagination } = response;
addCommentsToTree(newComments);
hasMore.current = pagination.hasMore;
setHasMoreState(pagination.hasMore);
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Failed to reset entity comments:");
}
finally {
loading.current = false;
setLoadingState(false);
}
}, [fetchManyComments, limit, sortBy, entityId]);
const loadMore = () => {
if (loading.current || !hasMore.current)
return;
setPage((prevPage) => {
return prevPage + 1;
});
};
(0, react_1.useEffect)(() => {
resetComments();
}, [resetComments]);
// useEffect to get a new batch of comments
(0, react_1.useEffect)(() => {
const loadMoreComments = async () => {
if (!entityId) {
return;
}
try {
loading.current = true;
setLoadingState(true);
const response = await fetchManyComments({
entityId,
page,
sortBy,
limit,
});
if (response) {
const { data: newComments, pagination } = response;
addCommentsToTree(newComments);
hasMore.current = pagination.hasMore;
setHasMoreState(pagination.hasMore);
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Loading more comments failed:");
}
finally {
loading.current = false;
setLoadingState(false);
}
};
// We only load more if th page changed
if (page > 1 && hasMore.current && !loading.current) {
loadMoreComments();
}
}, [page]);
return {
entityCommentsTree,
comments,
newComments,
loading: loadingState, // we use the state to trigger renders
hasMore: hasMoreState,
sortBy,
setSortBy,
loadMore,
addCommentsToTree,
removeCommentFromTree,
markCommentAsDeleted,
};
}
exports.default = useEntityComments;
//# sourceMappingURL=useEntityComments.js.map